diff --git a/.checkpatch.conf b/.checkpatch.conf index b2a7fdbad57..a1d04494df2 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -39,6 +39,7 @@ --exclude modules/tfm/tfm/boards/src --exclude modules/tfm/tfm/boards/common --exclude subsys/nrf_security/src/legacy +--exclude subsys/sdfw_services/services/.*/zcbor_generated --exclude doc/nrf/images --exclude doc/nrf/.*/images --exclude doc/nrf/.*/.*/images diff --git a/.github/labeler.yml b/.github/labeler.yml index b8b88710265..d74f1bb5302 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -8,18 +8,26 @@ # first branch. "manifest": - - "west.yml" +- changed-files: + - any-glob-to-any-file: + - "west.yml" "doc-required": - - "doc/**/*" - - "**/*.rst" +- changed-files: + - any-glob-to-any-file: + - "doc/**/*" + - "**/*.rst" "changelog-entry-required": - - all: ["!doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst"] +- all: + - changed-files: + - all-globs-to-all-files: ["!doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst"] "ble mesh": - - "subsys/bluetooth/mesh/*" - - "include/bluetooth/mesh/*" - - "samples/bluetooth/mesh/*" - - "doc/nrf/libraries/bluetooth_services/mesh/*" - - "doc/nrf/ug_bt_mesh*" +- changed-files: + - any-glob-to-any-file: + - "subsys/bluetooth/mesh/*" + - "include/bluetooth/mesh/*" + - "samples/bluetooth/mesh/*" + - "doc/nrf/libraries/bluetooth_services/mesh/*" + - "doc/nrf/ug_bt_mesh*" diff --git a/.github/test-spec.yml b/.github/test-spec.yml index 30c703c53b4..cba26ea7bd2 100644 --- a/.github/test-spec.yml +++ b/.github/test-spec.yml @@ -69,7 +69,6 @@ - "lib/data_fifo/**/*" - "lib/pcm_stream_channel_modifier/**/*" - "lib/tone/**/*" - - "lib/bin/bt_ll_acs_nrf53/**/*" "CI-iot-samples-test": - "include/modem/at_monitor.h" @@ -121,7 +120,7 @@ - "include/modem/at_params.h" - "include/modem/modem_key_mgmt.h" -"CI-boot-dfu-test": +"CI-dfu-test": - "include/bl*" - "include/fprotect.h" - "include/fw_info.*" @@ -150,6 +149,27 @@ - "tests/subsys/bootloader/**/*" - "tests/subsys/dfu/**/*" +"CI-boot-test": + - "include/bl*" + - "include/fprotect.h" + - "include/fw_info.*" + - "include/mgmt/*" + - "include/net/**/*" + - "cmake/*" + - "lib/lte_link_control/**/*" + - "modules/mcuboot/**/*" + - "modules/trusted-firmware-m/*" + - "samples/nrf5340/netboot/*" + - "samples/bootloader/**/*" + - "scripts/bootloader/**/*" + - "subsys/bootloader/**/*" + - "subsys/nonsecure/*" + - "subsys/partition_manager/*" + - "subsys/fw_info/**/*" + - "subsys/mgmt/**/*" + - "subsys/pcd/*" + - "tests/subsys/bootloader/**/*" + "CI-all-test": - "**/*partition_manager*/**/*" - "**/*partition_manager*" @@ -177,13 +197,23 @@ - any: - "include/bluetooth/**/*" - "!include/bluetooth/mesh/**/*" - - any: - - "samples/bluetooth/**/*" - - "!samples/bluetooth/mesh/**/*" - "subsys/nrf_rpc/**/*" - "subsys/mpsl/**/*" - "drivers/mpsl/**/*" +"CI-ble-samples-test": + - "samples/bluetooth/**/*" + - "subsys/nrf_rpc/**/*" + - "subsys/mpsl/**/*" + - "drivers/mpsl/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - any: + - "include/bluetooth/**/*" + - "!include/bluetooth/mesh/**/*" + + "CI-mesh-test": - "subsys/bluetooth/mesh/**/*" - "include/bluetooth/mesh/**/*" @@ -252,6 +282,7 @@ - "include/nrf_profiler.h" - "scripts/hid_configurator/**/*" - "subsys/bluetooth/services/**/*" + - "subsys/bluetooth/adv_prov/**/*" - "subsys/bluetooth/*" - "subsys/caf/**/*" - "subsys/app_event_manager/**/*" diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 8c2cd5003a9..fc1ecf04be1 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -11,12 +11,12 @@ jobs: run: | echo "$HOME/.local/bin" >> $GITHUB_PATH - - name: Checkout the code - uses: actions/checkout@v3 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: - path: ncs/nrf - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 + git-fetch-depth: 0 + git-ref: ${{ github.event.pull_request.head.sha }} + west-token: ${{ secrets.NCS_GITHUB_TOKEN }} - name: cache-pip uses: actions/cache@v3 @@ -34,13 +34,11 @@ jobs: grep -E "^west" scripts/requirements-fixed.txt | cut -d ' ' -f '1' | xargs pip3 install -U pip3 show -f west - - name: West init and update + - name: Run merge commits test env: BASE_REF: ${{ github.base_ref }} working-directory: ncs/nrf run: | - git config --global user.email "you@example.com" - git config --global user.name "Your Name" git remote -v # Ensure there's no merge commits in the PR [[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ @@ -49,8 +47,6 @@ jobs: git rebase origin/${BASE_REF} # debug git log --pretty=oneline | head -n 10 - west init -l . - west update --narrow -o=--depth=1 - name: Run CODEOWNERS test id: codeowners diff --git a/.github/workflows/create-upmerge-PRs.yml b/.github/workflows/create-upmerge-PRs.yml index 206610734e5..42d6a797276 100644 --- a/.github/workflows/create-upmerge-PRs.yml +++ b/.github/workflows/create-upmerge-PRs.yml @@ -16,11 +16,11 @@ jobs: if: github.repository == 'nrfconnect/sdk-nrf' runs-on: ubuntu-latest steps: - - name: Checkout the code - uses: actions/checkout@v3 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: - path: ncs/nrf - fetch-depth: 0 + git-fetch-depth: 0 + west-update-args: 'zephyr bsim mcuboot' - name: Install base dependencies working-directory: ncs @@ -28,13 +28,9 @@ jobs: pip3 install -r nrf/scripts/requirements-base.txt pip3 install -r nrf/scripts/requirements-extra.txt - - name: West init and update + - name: Get repo urls working-directory: ncs run: | - west init -l nrf - west update zephyr bsim mcuboot - git config --global user.email "noreply@nordicsemi.no" - git config --global user.name "Nordic Builder" echo "SDK_ZEPHYR=$(west list zephyr -f {url} | awk -F// '{print $NF}')" >> $GITHUB_ENV echo "SDK_MCUBOOT=$(west list mcuboot -f {url} | awk -F// '{print $NF}')" >> $GITHUB_ENV diff --git a/.github/workflows/docbuild.yml b/.github/workflows/docbuild.yml index 1922cd1c920..afa7092d497 100644 --- a/.github/workflows/docbuild.yml +++ b/.github/workflows/docbuild.yml @@ -29,18 +29,18 @@ jobs: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - steps: - - name: Checkout the code - uses: actions/checkout@v3 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: - path: ncs/nrf - fetch-depth: 0 + west-token: ${{ secrets.NCS_GITHUB_TOKEN }} + - name: cache-pip uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-doc-pip + - name: Install packages run: | sudo apt update @@ -57,11 +57,9 @@ jobs: sudo pip3 install -U setuptools wheel pip pip3 install -r nrf/doc/requirements.txt - - name: West init and update + - name: West zephyr-export working-directory: ncs run: | - west init -l nrf - west update west zephyr-export - name: Build documentation @@ -75,10 +73,10 @@ jobs: working-directory: ncs/nrf run: | MONITOR="monitor_${{ github.run_id }}.txt" - ARCHIVE="doc_build_${{ github.run_id }}.zip" # Create documentation upload files if [[ "${{ github.event_name }}" == "pull_request" ]]; then + ARCHIVE="doc_build_pr_${{ github.event.number }}.zip" echo "publish2 dev PR-${{ github.event.number }} ${ARCHIVE}" > "${MONITOR}" echo "${{ github.event.number }}" > pr.txt else @@ -91,6 +89,7 @@ jobs: echo "Not a release or latest, skipping publish" exit 0 fi + ARCHIVE="doc_build_${VERSION}.zip" echo "publish2 main ${VERSION} ${ARCHIVE}" > "${MONITOR}" fi diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 190a5b00e8f..5fee41d65f4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -20,8 +20,8 @@ jobs: uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: NordicBuilder + password: ${{ secrets.NCS_GITHUB_PKG_WRITE_TOKEN }} - name: Build and push Docker image run: | diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 7e7a0e0913d..e218a46d5ad 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -6,6 +6,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@v3.0.0 + - uses: actions/labeler@v5.0.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' + sync-labels: true diff --git a/.github/workflows/license-reusable.yml b/.github/workflows/license-reusable.yml index 9ee3c87412e..d35596e6d04 100644 --- a/.github/workflows/license-reusable.yml +++ b/.github/workflows/license-reusable.yml @@ -18,7 +18,6 @@ name: Reusable License Check on: workflow_call: inputs: - path: # Required path to your module relative to west workspace. type: string @@ -32,31 +31,22 @@ on: type: string default: nrf/scripts/ci/license_allow_list.yaml - nrf_repo: - # Optional URL of the custom "sdk-nrf" repository that contains license check - # script and the west manifest. By default official "sdk-nrf" repository is used. - type: string - default: https://github.com/nrfconnect/sdk-nrf - - nrf_rev: - # Optional revision of the "sdk-nrf" repository. By default, "main" is used. - type: string - default: main - jobs: license_job: runs-on: ubuntu-latest name: Run license checks on patch series (PR) steps: - - name: Checkout the code - uses: actions/checkout@v3 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: + git-fetch-depth: 0 + git-ref: ${{ github.event.pull_request.head.sha }} + west-token: ${{ secrets.NCS_GITHUB_TOKEN }} path: ncs/${{ inputs.path }} - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 + west-update-args: '-n zephyr bsim' - name: cache-pip - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-doc-pip @@ -70,32 +60,24 @@ jobs: pip3 install --user -U west pip3 show -f west - - name: Git config and rebase + - name: Git rebase env: BASE_REF: ${{ github.base_ref }} working-directory: ncs/${{ inputs.path }} run: | - git config --global user.email "you@example.com" - git config --global user.name "Your Name" git remote -v git branch git rebase origin/${BASE_REF} # debug git log --pretty=oneline | head -n 10 - - name: West init and update + - name: West zephyr-export working-directory: ncs env: PR_REF: ${{ github.event.pull_request.head.sha }} run: | export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/bin:$PATH" - if [ "${{ inputs.path }}" = "nrf" ]; then - west init -l nrf - else - west init -m ${{ inputs.nrf_repo }} --mr ${{ inputs.nrf_rev }} - fi - west update -n zephyr bsim west zephyr-export echo "ZEPHYR_BASE=$(pwd)/zephyr" >> $GITHUB_ENV # debug diff --git a/.github/workflows/oss-history.yml b/.github/workflows/oss-history.yml index 884bd1b1ca8..b5fd0796568 100644 --- a/.github/workflows/oss-history.yml +++ b/.github/workflows/oss-history.yml @@ -6,22 +6,20 @@ jobs: runs-on: ubuntu-latest name: Check OSS history steps: - - name: Checkout the code - uses: actions/checkout@v3 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: - path: ncs/nrf - fetch-depth: 0 + git-fetch-depth: 0 + west-update-args: '' - name: Install extra python dependencies run: | pip3 install west pip3 install -r ncs/nrf/scripts/requirements-extra.txt - - name: Set up the workspace + - name: Set upsteam + working-directory: ncs run: | - west init -l ncs/nrf - cd ncs - west update git -C zephyr remote add upstream https://github.com/zephyrproject-rtos/zephyr - name: Check manifest userdata @@ -33,4 +31,4 @@ jobs: uses: nrfconnect/action-oss-history@main with: workspace: 'ncs' - args: -p zephyr -p mcuboot -p trusted-firmware-m -p hostap -p wfa-qt-control-app + args: -p zephyr -p mcuboot -p hostap -p wfa-qt-control-app diff --git a/.github/workflows/pip-requirements.yml b/.github/workflows/pip-requirements.yml index c03d18b5956..bf80d768652 100644 --- a/.github/workflows/pip-requirements.yml +++ b/.github/workflows/pip-requirements.yml @@ -16,13 +16,11 @@ jobs: check-requirements: runs-on: ubuntu-20.04 steps: - - name: Checkout PR target branch - uses: actions/checkout@v4 + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main with: - ref: ${{ github.event.pull_request.head.sha }} - path: ncs/nrf - fetch-depth: 1 - persist-credentials: false + git-ref: ${{ github.event.pull_request.head.sha }} + west-update-args: '--narrow mcuboot zephyr' - name: Get python version id: pyv @@ -39,9 +37,7 @@ jobs: - name: Setup environment working-directory: ncs run: | - pip3 install --user -U setuptools wheel pip virtualenv virtualenvwrapper west - west init -l nrf - west update --narrow mcuboot zephyr + pip3 install --user -U setuptools wheel pip virtualenv virtualenvwrapper - name: Execute script diff action uses: nordicbuilder/action-script-diff@v0.1 diff --git a/.github/workflows/reapply-ci-trusted-author.yml b/.github/workflows/reapply-ci-trusted-author.yml index db2e13bb41e..cfc6e7e429c 100644 --- a/.github/workflows/reapply-ci-trusted-author.yml +++ b/.github/workflows/reapply-ci-trusted-author.yml @@ -1,24 +1,25 @@ name: Reapply CI-trusted-author label +# We want to use NordicBuilder instead of github-actions[bot] user +# github-actions[bot] is not trusted collaborator and labels added by it does not trigger Jenkins builds on: pull_request_target: types: [opened, reopened, synchronize] jobs: - remove_label: + reapply_label: + name: Reapply label if: ${{ contains(github.event.*.labels.*.name, 'CI-trusted-author') }} runs-on: ubuntu-latest - name: Remove label steps: - name: Remove CI-trusted-author label - uses: buildsville/add-remove-label@v2.0.0 - with: - token: '${{ secrets.GITHUB_TOKEN }}' - labels: CI-trusted-author - type: remove + run: gh pr edit ${{ github.event.pull_request.number }} --remove-label "CI-trusted-author" + env: + GH_TOKEN: ${{ secrets.NCS_JENKINS_TOKEN }} + GH_REPO: ${{ github.repository }} + - name: Add CI-trusted-author label - uses: buildsville/add-remove-label@v2.0.0 - with: - token: '${{ secrets.GITHUB_TOKEN }}' - labels: CI-trusted-author - type: add + run: gh pr edit ${{ github.event.pull_request.number }} --add-label "CI-trusted-author" + env: + GH_TOKEN: ${{ secrets.NCS_JENKINS_TOKEN }} + GH_REPO: ${{ github.repository }} diff --git a/.github/workflows/remove-ci-requested.yml b/.github/workflows/remove-ci-requested.yml index a2f4a285d9c..dd7549ba9e4 100644 --- a/.github/workflows/remove-ci-requested.yml +++ b/.github/workflows/remove-ci-requested.yml @@ -1,4 +1,4 @@ -name: Remove CI requested label +name: Remove CI-Requested label on: pull_request_target: @@ -6,12 +6,12 @@ on: jobs: remove_label: - runs-on: ubuntu-latest name: Remove label + if: ${{ contains(github.event.*.labels.*.name, 'CI-Requested') }} + runs-on: ubuntu-latest steps: - - name: removelabel - uses: buildsville/add-remove-label@v2.0.0 - with: - token: '${{ secrets.GITHUB_TOKEN }}' - labels: CI-Requested - type: remove + - name: Remove label + run: gh pr edit ${{ github.event.pull_request.number }} --remove-label "CI-Requested" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} diff --git a/.github/workflows/src-mirror.yml b/.github/workflows/src-mirror.yml new file mode 100644 index 00000000000..c02df548c7d --- /dev/null +++ b/.github/workflows/src-mirror.yml @@ -0,0 +1,34 @@ +name: src-mirror +on: + push: + tags: + - '*' + +jobs: + zip-and-upload: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: nordicbuilder/action-checkout-west-update@main + with: + git-fetch-depth: 0 + path: workspace/nrf + + - name: Create tar + run: > + tar -C ./workspace -cvf src.tar.gz . + + - name: Set up JFrog CLI + uses: jfrog/setup-jfrog-cli@v4 + + - name: Configure and Upload to Artifactory + env: + ARTIFACTORY_URL: https://eu.files.nordicsemi.com/artifactory + REPOSITORY: ncs-src-mirror + FILE_PATH: src.tar.gz + TARGET_PATH: external/${{ github.ref_name }}/ + run: > + jfrog rt u $FILE_PATH $REPOSITORY/$TARGET_PATH + --url=$ARTIFACTORY_URL + --user=${{ secrets.COM_NORDICSEMI_FILES_USERNAME }} + --password=${{ secrets.COM_NORDICSEMI_FILES_PASSWORD }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5eb7352ddff..9356d847b4b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v3 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.' diff --git a/CODEOWNERS b/CODEOWNERS index da2f8246ce6..a7dda9809d8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -30,11 +30,12 @@ # Applications /applications/asset_tracker_v2/ @nrfconnect/ncs-cia @coderbyheart /applications/connectivity_bridge/ @nrfconnect/ncs-cia @nordic-auko +/applications/ipc_radio/ @dchat-nordic /applications/machine_learning/ @pdunaj /applications/matter_bridge/ @Damian-Nordic @kkasperczyk-no /applications/matter_weather_station/ @Damian-Nordic @kkasperczyk-no /applications/nrf_desktop/ @MarekPieta -/applications/nrf5340_audio/ @koffes @alexsven @erikrobstad @rick1082 @gWacey +/applications/nrf5340_audio/ @nrfconnect/ncs-audio /applications/serial_lte_modem/ @SeppoTakalo @MarkusLassila @rlubos @tomi-font /applications/zigbee_weather_station/ @milewr # Boards @@ -57,13 +58,15 @@ Kconfig* @tejlmand /doc/**/conf.py @carlescufi /doc/kconfig/ @gmarull /doc/nrf/ @carlescufi +/doc/nrf/device_guides/working_with_nrf/nrf54h/ @FrancescoSer +/doc/nrf/device_guides/working_with_nrf/nrf54l/ @annwoj /doc/nrfx/ @gmarull /doc/matter/ @gmarull /doc/mcuboot/ @carlescufi /doc/nrfxlib/ @gmarull /doc/versions.json @carlescufi /doc/custom.properties @gmarull -/doc/tags.yml @gmarull +/doc/tags.yml @gmarull @umapraseeda @b-gent /doc/requirements.txt @gmarull # General top-level docs /doc/nrf/config_and_build/ @greg-fer @@ -71,6 +74,8 @@ Kconfig* @tejlmand /doc/nrf/security/ @greg-fer /doc/nrf/test_and_optimize/ @greg-fer /doc/nrf/*.rst @greg-fer +# Protocols related docs +/doc/nrf/protocols/thread/*.rst @wiba-nordic # All subfolders /drivers/ @anangl /drivers/serial/ @nordic-krch @anangl @@ -81,13 +86,12 @@ Kconfig* @tejlmand /drivers/wifi/nrf700x/ @krish2718 @sachinthegreen @rado17 @rlubos /dts/ @anangl /ext/ @carlescufi -/ext/oberon/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky /include/ @anangl @rlubos /include/net/azure_* @nrfconnect/ncs-cia @coderbyheart /include/net/wifi_credentials.h @nrfconnect/ncs-cia /include/net/nrf_cloud_* @plskeggs @jayteemo @glarsennordic /include/bluetooth/ @alwa-nordic @jori-nordic @KAGA164 -/include/bluetooth/services/fast_pair.h @alstrzebonski @MarekPieta @kapi-no +/include/bluetooth/services/fast_pair/ @alstrzebonski @MarekPieta @kapi-no /include/bluetooth/adv_prov.h @MarekPieta @kapi-no @KAGA164 /include/bluetooth/mesh/ @ludvigsj /include/caf/ @pdunaj @@ -96,6 +100,7 @@ Kconfig* @tejlmand /include/mpsl/ @nrfconnect/ncs-dragoon /include/net/ @rlubos /include/nfc/ @anangl @grochu +/include/sdfw/ @anhmolt @hakonfam @jonathannilsen /include/shell/ @nordic-krch /lib/bin/ @rlubos @lemrey /lib/adp536x/ @nrfconnect/ncs-cia @@ -133,16 +138,18 @@ Kconfig* @tejlmand /lib/modem_slm/ @SeppoTakalo @MarkusLassila @tomi-font /lib/modem_attest_token/ @jayteemo /lib/qos/ @nrfconnect/ncs-cia -/lib/contin_array/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/lib/data_fifo/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/lib/pcm_mix/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/lib/pcm_stream_channel_modifier/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/lib/tone/ @koffes @alexsven @erikrobstad @rick1082 @gWacey +/lib/contin_array/ @nrfconnect/ncs-audio +/lib/data_fifo/ @nrfconnect/ncs-audio +/lib/pcm_mix/ @nrfconnect/ncs-audio +/lib/pcm_stream_channel_modifier/ @nrfconnect/ncs-audio +/lib/sample_rate_converter/ @andvib @gWacey +/lib/tone/ @nrfconnect/ncs-audio /modules/ @tejlmand /modules/hostap/ @krish2718 @jukkar @rado17 @sachinthegreen @rlubos /modules/mcuboot/ @de-nordic @nordicjm /modules/cjson/ @nrfconnect/ncs-cia @plskeggs @sigvartmh /modules/trusted-firmware-m/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky +/modules/coremark/ @zycz /samples/ @nrfconnect/ncs-test-leads /samples/net/ @nrfconnect/ncs-cia @lemrey /samples/sensor/bh1749/ @nrfconnect/ncs-cia @@ -190,15 +197,21 @@ Kconfig* @tejlmand /samples/CMakeLists.txt @tejlmand /samples/nrf5340/netboot/ @hakonfam /samples/nrf5340/multiprotocol_rpmsg/ @hubertmis +/samples/sdfw/ @hakonfam @jonathannilsen +/samples/sdfw/ssf_client/ @anhmolt /samples/wifi/provisioning/ @wentong-li @bama-nordic /samples/wifi/radio_test/ @bama-nordic @sachinthegreen /samples/wifi/scan/ @D-Triveni @bama-nordic /samples/wifi/shell/ @krish2718 @sachinthegreen @rado17 @rlubos /samples/wifi/sta/ @D-Triveni @bama-nordic -/samples/wifi/sr_coex/ @muraliThokala @bama-nordic +/samples/wifi/ble_coex/ @muraliThokala @bama-nordic /samples/wifi/shutdown/ @krish2718 @sachinthegreen /samples/wifi/twt/ @chiranjeevi2776 @krish2718 /samples/wifi/throughput/ @SusanGRapaka @D-Triveni +/samples/wifi/raw_tx_packet/ @D-Triveni +/samples/wifi/softap/ @D-Triveni @krish2718 +/samples/wifi/monitor/ @chiranjeevi2776 @krish2718 +/samples/benchmarks/coremark/ @zycz /scripts/ @tejlmand @nrfconnect/ncs-test-leads /scripts/hid_configurator/ @MarekPieta /scripts/tools-versions-*.txt @tejlmand @grho @shanthanordic @ihansse @@ -210,11 +223,12 @@ Kconfig* @tejlmand /scripts/print_toolchain_checksum.sh @nrfconnect/ncs-ci /share/zephyrbuild-package/ @tejlmand /share/ncs-package/ @tejlmand +/snippets/nrf91-modem-trace-ext-flash/ @nrfconnect/ncs-cia /snippets/nrf91-modem-trace-uart/ @eivindj-nordic /snippets/tfm-enable-share-uart/ @nrfconnect/ncs-cia /snippets/nrf70-debug/ @krish2718 @sachinthegreen /snippets/nrf70-fw-patch-ext-flash/ @krish2718 @sachinthegreen -/subsys/audio_module/ @koffes @alexsven @erikrobstad @rick1082 @gWacey +/subsys/audio_module/ @nrfconnect/ncs-audio /subsys/bluetooth/ @alwa-nordic @jori-nordic @carlescufi @KAGA164 /subsys/bluetooth/mesh/ @ludvigsj /subsys/bluetooth/controller/ @nrfconnect/ncs-dragoon @@ -257,13 +271,16 @@ Kconfig* @tejlmand /subsys/pcd/ @hakonfam /subsys/nrf_profiler/ @pdunaj /subsys/shell/ @nordic-krch +/subsys/sdfw_services/ @anhmolt @hakonfam @jonathannilsen +/subsys/suit/ @tomchy /subsys/nrf_security/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky -/subsys/secure_storage/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky +/subsys/trusted_storage/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky +/subsys/uart_async_adapter/ @rakons /subsys/net_core_monitor/ @maje-emb /subsys/zigbee/ @milewr /tests/ @PerMac @katgiadla /tests/bluetooth/tester/ @carlescufi @ludvigsj -/tests/bluetooth/iso/ @koffes @alexsven @erikrobstad @rick1082 @gWacey @Frodevan +/tests/bluetooth/iso/ @nrfconnect/ncs-audio @Frodevan /tests/crypto/ @stephen-nordic @magnev /tests/drivers/flash_patch/ @oyvindronningstad /tests/drivers/fprotect/ @oyvindronningstad @@ -290,16 +307,17 @@ Kconfig* @tejlmand /tests/lib/nrf_modem_lib/nrf91_sockets/ @MirkoCovizzi /tests/lib/pdn/ @lemrey @eivindj-nordic /tests/lib/ram_pwrdn/ @Damian-Nordic -/tests/lib/contin_array/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/tests/lib/data_fifo/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/tests/lib/pcm_mix/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/tests/lib/pcm_stream_channel_modifier/ @koffes @alexsven @erikrobstad @rick1082 @gWacey -/tests/lib/tone/ @koffes @alexsven @erikrobstad @rick1082 @gWacey +/tests/lib/contin_array/ @nrfconnect/ncs-audio +/tests/lib/data_fifo/ @nrfconnect/ncs-audio +/tests/lib/pcm_mix/ @nrfconnect/ncs-audio +/tests/lib/pcm_stream_channel_modifier/ @nrfconnect/ncs-audio +/tests/lib/sample_rate_converter/ @andvib @gWacey +/tests/lib/tone/ @nrfconnect/ncs-audio /tests/modules/lib/zcbor/ @oyvindronningstad /tests/modules/mcuboot/direct_xip/ @hakonfam /tests/modules/mcuboot/external_flash/ @hakonfam @sigvartmh -/tests/nrf5340_audio/ @koffes @alexsven @erikrobstad @rick1082 @nordic-auko -/tests/subsys/audio_module/ @koffes @alexsven @erikrobstad @rick1082 @gWacey +/tests/nrf5340_audio/ @nrfconnect/ncs-audio @nordic-auko +/tests/subsys/audio_module/ @nrfconnect/ncs-audio /tests/subsys/bluetooth/gatt_dm/ @doki-nordic /tests/subsys/bluetooth/mesh/ @ludvigsj /tests/subsys/bluetooth/fast_pair/ @alstrzebonski @MarekPieta @kapi-no @@ -323,6 +341,7 @@ Kconfig* @tejlmand /tests/subsys/partition_manager/region/ @hakonfam @sigvartmh /tests/subsys/pcd/ @hakonfam @sigvartmh /tests/subsys/nrf_profiler/ @pdunaj @MarekPieta +/tests/subsys/sdfw_services/ @anhmolt @hakonfam @jonathannilsen /tests/subsys/zigbee/ @milewr /tests/tfm/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky @stephen-nordic @magnev /tests/unity/ @nordic-krch diff --git a/README.rst b/README.rst index d94fe815533..04211a26660 100644 --- a/README.rst +++ b/README.rst @@ -6,14 +6,13 @@ nRF Connect SDK: sdk-nrf :depth: 2 This repository contains the core of nRF Connect SDK, including subsystems, -libraries, samples and applications. +libraries, samples, and applications. It is also the SDK's west manifest repository, containing the nRF Connect SDK manifest (west.yml). Documentation ************* -Official documentation at: +Official latest documentation at https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/index.html -* Latest: http://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest -* All versions: http://developer.nordicsemi.com/nRF_Connect_SDK/doc/ +For earlier versions, open the latest version and use the drop-down under the title header. diff --git a/VERSION b/VERSION index cb3e9601725..40bd3f64267 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5.99 +2.6.99 diff --git a/applications/asset_tracker_v2/CMakeLists.txt b/applications/asset_tracker_v2/CMakeLists.txt index 47129e07388..55cbf60d8eb 100644 --- a/applications/asset_tracker_v2/CMakeLists.txt +++ b/applications/asset_tracker_v2/CMakeLists.txt @@ -30,16 +30,19 @@ add_subdirectory_ifdef(CONFIG_WATCHDOG_APPLICATION src/watchdog) # Include nRF modem library header file for PC builds. # These are used throughout the application in type definitions. if (CONFIG_BOARD_QEMU_X86 OR CONFIG_BOARD_NATIVE_POSIX) - target_include_directories(app PRIVATE ${NRFXLIB_DIR}/nrf_modem/include/) + target_include_directories(app PRIVATE ${NRFXLIB_DIR}/nrf_modem/include/) - # Make folder containing certificates global so that it can be located by the configured - # cloud library. - zephyr_include_directories(src/cloud-certs) + # Make the folder that contains the certificates global so that it can be located by the + # nRF Cloud library. For the other clouds integrations, the certificates are handled by the + # MQTT helper library, see CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES. + if (CONFIG_NRF_CLOUD_PROVISION_CERTIFICATES) + zephyr_include_directories(src/cloud-certs) + endif() - target_compile_options(app PRIVATE - -DCONFIG_LTE_NEIGHBOR_CELLS_MAX=10) + target_compile_options(app PRIVATE + -DCONFIG_LTE_NEIGHBOR_CELLS_MAX=10) endif() if(CONFIG_ASSET_TRACKER_V2_LTO) - target_compile_options(app PRIVATE "-flto") + target_compile_options(app PRIVATE "-flto") endif() diff --git a/applications/asset_tracker_v2/boards/native_sim.conf b/applications/asset_tracker_v2/boards/native_sim.conf index 9bd7854b5d2..05e817b38fe 100644 --- a/applications/asset_tracker_v2/boards/native_sim.conf +++ b/applications/asset_tracker_v2/boards/native_sim.conf @@ -116,3 +116,6 @@ CONFIG_BUILD_S1_VARIANT=n # Watchdog CONFIG_WATCHDOG_APPLICATION=n + +# Cloud module certificates +CONFIG_MQTT_HELPER_CERTIFICATES_FOLDER="src/cloud-certs" diff --git a/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.conf b/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.conf new file mode 100644 index 00000000000..6448a9bb28c --- /dev/null +++ b/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.conf @@ -0,0 +1,18 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# CAF - Common Application Framework +CONFIG_GPIO=y +CONFIG_LED_GPIO=y + +# Enable external flash +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y diff --git a/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.overlay b/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.overlay new file mode 100644 index 00000000000..fc12cd4b546 --- /dev/null +++ b/applications/asset_tracker_v2/boards/nrf9151dk_nrf9151_ns.overlay @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + /delete-node/ leds; + + leds0 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED0"; + led0: led_0 { + status = "okay"; + gpios = <&gpio0 0 0>; + label = "Green LED 1"; + }; + }; + + leds1 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED1"; + led1: led_1 { + gpios = <&gpio0 1 0>; + label = "Green LED 2"; + }; + }; + + leds2 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED2"; + led2: led_2 { + gpios = <&gpio0 4 0>; + label = "Green LED 3"; + }; + }; + + leds3 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED3"; + led3: led_3 { + gpios = <&gpio0 5 0>; + label = "Green LED 4"; + }; + }; + + /* Configure partition manager to use gd25wb256 as the external flash */ + chosen { + nordic,pm-ext-flash = &gd25wb256; + }; + + aliases { + ext-flash = &gd25wb256; + }; +}; + +&gd25wb256 { + status = "okay"; +}; diff --git a/applications/asset_tracker_v2/boards/nrf9160dk_nrf9160_ns.overlay b/applications/asset_tracker_v2/boards/nrf9160dk_nrf9160_ns.overlay index 6ae896b9fd7..886f146596c 100644 --- a/applications/asset_tracker_v2/boards/nrf9160dk_nrf9160_ns.overlay +++ b/applications/asset_tracker_v2/boards/nrf9160dk_nrf9160_ns.overlay @@ -41,4 +41,17 @@ label = "Green LED 4"; }; }; + + /* Configure partition manager to use mx25r64 as the external flash */ + chosen { + nordic,pm-ext-flash = &mx25r64; + }; + + aliases { + ext-flash = &mx25r64; + }; +}; + +&mx25r64 { + status = "okay"; }; diff --git a/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.conf b/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.conf new file mode 100644 index 00000000000..602fee6bcbe --- /dev/null +++ b/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.conf @@ -0,0 +1,29 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Configuration file for Thingy:91 X. +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# Configuration related to external sensors. +CONFIG_EXTERNAL_SENSORS=y + +# BME680 - Temperature and humidity sensor. +CONFIG_BME680=y + +# CAF - Common Application Framework +CONFIG_PWM=y +CONFIG_LED_GPIO=y + +CONFIG_PM_PARTITION_REGION_SETTINGS_STORAGE_EXTERNAL=y + +CONFIG_ADXL367=y +CONFIG_ADXL367_TRIGGER_GLOBAL_THREAD=y +CONFIG_ADXL367_REFERENCED_ACTIVITY_DETECTION_MODE=y +# Use a default of 0.25g +CONFIG_ADXL367_ACTIVITY_THRESHOLD=1000 +# App does not set activity time, set to 0 to disable +CONFIG_ADXL367_ACTIVITY_TIME=0 diff --git a/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.overlay b/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.overlay new file mode 100644 index 00000000000..c75d1a28aff --- /dev/null +++ b/applications/asset_tracker_v2/boards/thingy91x_nrf9151_ns.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + aliases { + temp-sensor = &bme680; + humidity-sensor = &bme680; + pressure-sensor = &bme680; + iaq-sensor = &bme680; + accelerometer = &accelerometer_lp; + }; +}; + +&accelerometer_lp { + status = "okay"; + odr = < 5 >; +}; + +&bme680 { + status = "okay"; +}; diff --git a/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.conf b/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.conf new file mode 100644 index 00000000000..233bd8b63f1 --- /dev/null +++ b/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# MCUboot config to enable secondary slot on the external flash + +CONFIG_FLASH=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_MULTITHREADING=y +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y diff --git a/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.overlay b/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.overlay new file mode 100644 index 00000000000..94d9c336394 --- /dev/null +++ b/applications/asset_tracker_v2/child_image/mcuboot/boards/nrf9151dk_nrf9151.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&gd25wb256 { + status = "okay"; +}; + +/ { + /* Configure partition manager to use gd25wb256 as the external flash */ + chosen { + nordic,pm-ext-flash = &gd25wb256; + }; +}; diff --git a/applications/asset_tracker_v2/configuration/memfault/memfault_metrics_heartbeat_config.def b/applications/asset_tracker_v2/configuration/memfault/memfault_metrics_heartbeat_config.def index 79f4e3015d3..5a9a2c9297a 100644 --- a/applications/asset_tracker_v2/configuration/memfault/memfault_metrics_heartbeat_config.def +++ b/applications/asset_tracker_v2/configuration/memfault/memfault_metrics_heartbeat_config.def @@ -2,6 +2,6 @@ * Please refer to https://docs.memfault.com/docs/embedded/metrics-api for more details. */ -MEMFAULT_METRICS_KEY_DEFINE(GnssTimeToFix, kMemfaultMetricType_Unsigned) -MEMFAULT_METRICS_KEY_DEFINE(GnssSatellitesTracked, kMemfaultMetricType_Unsigned) -MEMFAULT_METRICS_KEY_DEFINE(LocationTimeoutSearchTime, kMemfaultMetricType_Unsigned) +MEMFAULT_METRICS_KEY_DEFINE(gnss_time_to_fix_ms, kMemfaultMetricType_Unsigned) +MEMFAULT_METRICS_KEY_DEFINE(gnss_satellites_tracked_count, kMemfaultMetricType_Unsigned) +MEMFAULT_METRICS_KEY_DEFINE(location_timeout_search_time_ms, kMemfaultMetricType_Unsigned) diff --git a/applications/asset_tracker_v2/doc/asset_tracker_v2_description.rst b/applications/asset_tracker_v2/doc/asset_tracker_v2_description.rst index 297de51ce98..d7a2b1e16dc 100644 --- a/applications/asset_tracker_v2/doc/asset_tracker_v2_description.rst +++ b/applications/asset_tracker_v2/doc/asset_tracker_v2_description.rst @@ -15,6 +15,8 @@ The Asset Tracker v2 application is built on the following principles: * Batching of data - Data is batched to reduce the number of messages transmitted, and to be able to retain collected data while the device is offline. * Configurable at run time - The application behavior (for example, accelerometer sensitivity or GNSS timeout) can be configured at run time. This improves the development experience with individual devices or when debugging the device behavior in specific areas and situations. It also reduces the cost for transmitting data to the devices by reducing the frequency of sending firmware updates to the devices. +.. _asset_tracker_v2_requirements: + Requirements ************ @@ -33,7 +35,7 @@ Following are the cloud services that are supported by the application: * `AWS IoT Core`_ * `Azure IoT Hub`_ * `nRF Cloud`_ -* `LwM2M`_ v1.1 compliant service (for example, AVSystem's `Coiote Device Management`_, `Leshan LwM2M server `_). +* `LwM2M`_ v1.1 compliant service (for example, AVSystem's `Coiote Device Management`_, `Leshan LwM2M Server `_). To know more about the AVSystem integration with |NCS|, see :ref:`ug_avsystem`. To run the application on a development kit and connect to a cloud service, you must complete the following steps: @@ -67,7 +69,7 @@ To set up a cloud service to work with the application firmware, complete the st * Azure IoT Hub - :ref:`lib_azure_iot_hub`. This step retrieves a *security tag* and *ID scope* that will be needed during the configuration of the firmware. - Make sure to follow the steps documented in the :ref:`dps_config` section to enable Device Provisioning Service (DPS). + Make sure to follow the steps documented in the :ref:`configuration using DPS ` section to enable Device Provisioning Service (DPS). * AVSystem's LwM2M Coiote Device Management - :ref:`server_setup_lwm2m_client`. No additional configuration is needed if the server is set up according to the linked documentation. @@ -105,9 +107,11 @@ The application provides predefined configuration files for typical use cases. Following are the available configuration files: * :file:`prj.conf` - Configuration file for all build targets. -* :file:`boards/.conf` - Configuration overlay file specific for . +* :file:`boards/.conf` - Configuration file specific for a build target specified with ****, where **** is the build target, for example ``nrf9161dk_nrf9161_ns``. This file is automatically merged with the :file:`prj.conf` file when you build for that target. +The :file:`include//led_state_def.h` header file describes the LED behavior of the CAF LEDs module. + Overlay configurations files that enable specific features: * :file:`overlay-aws.conf` - Configuration file that enables communication with AWS IoT Core. @@ -127,8 +131,6 @@ Custom DTC overlay file for enabling a specific feature: Multiple overlay files can be included to enable multiple features at the same time. -Header file that describes the LED behavior of the CAF LEDs module: file:`include//led_state_def.h`. - .. note:: Generally, Kconfig overlays have an ``overlay-`` prefix and a :file:`.conf` extension. @@ -167,7 +169,7 @@ Building and running ******************** This application can be found under :file:`applications/asset_tracker_v2` in the |NCS| folder structure. -See :ref:`programming` for information about how to build and program the application. +See :ref:`building` for information about how to build the application and :ref:`programming` for information about how to program it. Testing ======= diff --git a/applications/asset_tracker_v2/doc/cloud_module.rst b/applications/asset_tracker_v2/doc/cloud_module.rst index 410357baf76..8a3488c6d4f 100644 --- a/applications/asset_tracker_v2/doc/cloud_module.rst +++ b/applications/asset_tracker_v2/doc/cloud_module.rst @@ -95,7 +95,7 @@ This enables the cloud to issue FOTA updates and update the application and mode For additional documentation on the various FOTA implementations, refer to the respective client library documentation linked to in :ref:`Integration layers `. Full modem FOTA updates are only supported by nRF Cloud. -This application implements full modem FOTA only for the nRF9161 DK, and for nRF9160 DK version 0.14.0 and higher. +This application implements full modem FOTA for the nRF91x1 DKs and for the nRF9160 DK version 0.14.0 and higher. To enable full modem FOTA, add the ``-DEXTRA_CONF_FILE=overlay-full_modem_fota.conf`` parameter to your build command. Also, specify your development kit version by appending it to the board name. @@ -188,9 +188,9 @@ If not using the default DPS (Device Provisioning Service) host, ensure that the Configurations for LwM2M integration layer ------------------------------------------ -When building for LwM2M, the cloud module's default configuration is to communicate with AVSystem's `Coiote Device Management`_, with a runtime provisioned `Pre-shared key (PSK)`_ set by the :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK` option. +When building for LwM2M, the cloud module's default configuration is to communicate with AVSystem's `Coiote Device Management`_, with a runtime provisioned `pre-shared key `_ set by the :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK` option. This enables the device to work with `Coiote Device Management`_ without provisioning the PSK to the modem before running the application. -To allow the device to communicate with other LwM2M servers, modify the default configuration by changing the following Kconfig options: +To allow the device to communicate with other LwM2M Servers, modify the default configuration by changing the following Kconfig options: * :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_SERVER` * :kconfig:option:`CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP` diff --git a/applications/asset_tracker_v2/doc/cloud_wrapper.rst b/applications/asset_tracker_v2/doc/cloud_wrapper.rst index fdd896216f5..037d1396258 100644 --- a/applications/asset_tracker_v2/doc/cloud_wrapper.rst +++ b/applications/asset_tracker_v2/doc/cloud_wrapper.rst @@ -53,7 +53,7 @@ The application integrates LwM2M through the following APIs: Bootstrapping and credential handling ------------------------------------- -When the option :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK` is enabled, the modem is provisioned at run time after boot with a `Pre-Shared Key (PSK)`_ set by :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK`. +When the option :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK` is enabled, the modem is provisioned at run time after boot with a `pre-shared key (PSK) `_ set by :kconfig:option:`CONFIG_LWM2M_INTEGRATION_PSK`. If :kconfig:option:`CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP` is enabled, the PSK is provisioned to a security tag dedicated to the bootstrap server connection. During bootstrapping, the application receives a separate newly generated key from the bootstrap server that is provisioned to a security tag dedicated to the management server connection. @@ -115,40 +115,40 @@ The following tables list the various topics used in the AWS IoT implementation. Device-to-cloud (D2C) --------------------- -+------------------------------+--------------------------------------------------------+ -| Data | Topic | -+==============================+========================================================+ -| A-GNSS requests | ``/agps/get`` | -+------------------------------+--------------------------------------------------------+ -| P-GPS requests | ``/pgps/get`` | -+------------------------------+--------------------------------------------------------+ -| Neighbor cell measurements | ``/ncellmeas`` | -+------------------------------+--------------------------------------------------------+ -| Button presses | ``/messages`` | -+------------------------------+--------------------------------------------------------+ -| Sensor/device data | ``$aws/things//shadow/update`` | -+------------------------------+--------------------------------------------------------+ -| Device configuration | ``$aws/things//shadow/update`` | -+------------------------------+--------------------------------------------------------+ -| Buffered sensor/device data | ``/batch`` | -+------------------------------+--------------------------------------------------------+ ++------------------------------+---------------------------------------------------------+ +| Data | Topic | ++==============================+=========================================================+ +| A-GNSS requests | ``/agnss/get`` | ++------------------------------+---------------------------------------------------------+ +| P-GPS requests | ``/pgps/get`` | ++------------------------------+---------------------------------------------------------+ +| Neighbor cell measurements | ``/ncellmeas`` | ++------------------------------+---------------------------------------------------------+ +| Button presses | ``/messages`` | ++------------------------------+---------------------------------------------------------+ +| Sensor/device data | ``$aws/things//shadow/update`` | ++------------------------------+---------------------------------------------------------+ +| Device configuration | ``$aws/things//shadow/update`` | ++------------------------------+---------------------------------------------------------+ +| Buffered sensor/device data | ``/batch`` | ++------------------------------+---------------------------------------------------------+ Cloud-to-device (C2D) --------------------- -+------------------------------+--------------------------------------------------------+ -| Data | Topic | -+==============================+========================================================+ -| A-GNSS response | ``/agps`` | -+------------------------------+--------------------------------------------------------+ -| P-GPS response | ``/pgps`` | -+------------------------------+--------------------------------------------------------+ -| Device configuration updates | ``$aws/things//shadow/delta`` | -| +--------------------------------------------------------+ -| | ``$aws/things//shadow/get/accepted`` | -| +--------------------------------------------------------+ -| | ``$aws/things//shadow/get/accepted/desired/cfg`` | -+------------------------------+--------------------------------------------------------+ ++------------------------------+---------------------------------------------------------+ +| Data | Topic | ++==============================+=========================================================+ +| A-GNSS response | ``/agnss`` | ++------------------------------+---------------------------------------------------------+ +| P-GPS response | ``/pgps`` | ++------------------------------+---------------------------------------------------------+ +| Device configuration updates | ``$aws/things//shadow/delta`` | +| +---------------------------------------------------------+ +| | ``$aws/things//shadow/get/accepted`` | +| +---------------------------------------------------------+ +| | ``$aws/things//shadow/get/accepted/desired/cfg`` | ++------------------------------+---------------------------------------------------------+ Azure IoT Hub topics ==================== @@ -159,36 +159,36 @@ For more information on MQTT topics and property bags in Azure IoT Hub, refer to Device-to-cloud (D2C) --------------------- -+------------------------------+---------------------------------------------+--------------+ -| Data | Topic | Property bag | -+==============================+=============================================+==============+ -| A-GNSS requests | ``devices//messages/events/`` | ``agps=get`` | -+------------------------------+---------------------------------------------+--------------+ -| P-GPS requests | ``devices//messages/events/`` | ``pgps=get`` | -+------------------------------+---------------------------------------------+--------------+ -| Neighbor cell measurements | ``devices//messages/events/`` | ``ncellmeas``| -+------------------------------+---------------------------------------------+--------------+ -| Button presses | ``devices//messages/events/`` | NA | -+------------------------------+---------------------------------------------+--------------+ -| Sensor/device data | ``$iothub/twin/PATCH/properties/reported/`` | NA | -+------------------------------+---------------------------------------------+--------------+ -| Device configuration | ``$iothub/twin/PATCH/properties/reported/`` | NA | -+------------------------------+---------------------------------------------+--------------+ -| Buffered sensor/device data | ``devices//messages/events/`` | ``batch`` | -+------------------------------+---------------------------------------------+--------------+ ++------------------------------+---------------------------------------------+---------------+ +| Data | Topic | Property bag | ++==============================+=============================================+===============+ +| A-GNSS requests | ``devices//messages/events/`` | ``agnss=get`` | ++------------------------------+---------------------------------------------+---------------+ +| P-GPS requests | ``devices//messages/events/`` | ``pgps=get`` | ++------------------------------+---------------------------------------------+---------------+ +| Neighbor cell measurements | ``devices//messages/events/`` | ``ncellmeas`` | ++------------------------------+---------------------------------------------+---------------+ +| Button presses | ``devices//messages/events/`` | NA | ++------------------------------+---------------------------------------------+---------------+ +| Sensor/device data | ``$iothub/twin/PATCH/properties/reported/`` | NA | ++------------------------------+---------------------------------------------+---------------+ +| Device configuration | ``$iothub/twin/PATCH/properties/reported/`` | NA | ++------------------------------+---------------------------------------------+---------------+ +| Buffered sensor/device data | ``devices//messages/events/`` | ``batch`` | ++------------------------------+---------------------------------------------+---------------+ Cloud-to-device (C2D) --------------------- -+------------------------------+------------------------------------------+----------------+ -| Data | Topic | Property bag | -+==============================+==========================================+================+ -| A-GNSS response | ``devices//messages/devicebound/`` | ``agps=result``| -+------------------------------+------------------------------------------+----------------+ -| P-GPS response | ``devices//messages/devicebound/`` | ``pgps=result``| -+------------------------------+------------------------------------------+----------------+ -| Device configuration updates | ``$iothub/twin/res//`` | NA | -+------------------------------+------------------------------------------+----------------+ ++------------------------------+------------------------------------------+-----------------+ +| Data | Topic | Property bag | ++==============================+==========================================+=================+ +| A-GNSS response | ``devices//messages/devicebound/`` | ``agnss=result``| ++------------------------------+------------------------------------------+-----------------+ +| P-GPS response | ``devices//messages/devicebound/`` | ``pgps=result`` | ++------------------------------+------------------------------------------+-----------------+ +| Device configuration updates | ``$iothub/twin/res//`` | NA | ++------------------------------+------------------------------------------+-----------------+ nRF Cloud topics ================ @@ -275,7 +275,7 @@ For more information on objects used in LwM2M, refer to the `OMA LwM2M Object an Uploading XML definition for configuration object ------------------------------------------------- -The application defines a proprietary ``Configuration object`` that the LwM2M server needs to be made aware of to enable the manipulation of its resources using the web console. +The application defines a proprietary ``Configuration object`` that the LwM2M Server needs to be made aware of to enable the manipulation of its resources using the web console. If you are using `Coiote Device Management`_, complete the following steps to add the LwM2M object definition: 1. Open `Coiote Device Management server`_. diff --git a/applications/asset_tracker_v2/doc/debug_module.rst b/applications/asset_tracker_v2/doc/debug_module.rst index e686639bc8a..3cb0581e6f1 100644 --- a/applications/asset_tracker_v2/doc/debug_module.rst +++ b/applications/asset_tracker_v2/doc/debug_module.rst @@ -25,9 +25,9 @@ Memfault The debug module uses `Memfault SDK`_ to track |NCS| specific metrics such as LTE and stack metrics. In addition, the following types of custom Memfault metrics are defined and tracked when compiling in the debug module: - * ``GnssTimeToFix`` - Time duration between the start of a GNSS search and obtaining a fix. - * ``GnssSatellitesTracked`` - Number of satellites tracked during a GNSS search window. - * ``LocationTimeoutSearchTime`` - Time duration between the start of a location search and a search timeout. + * ``gnss_time_to_fix_ms`` - Time duration between the start of a GNSS search and obtaining a fix. + * ``gnss_satellites_tracked_count`` - Number of satellites tracked during a GNSS search window. + * ``location_timeout_search_time_ms`` - Time duration between the start of a location search and a search timeout. The debug module also implements `Memfault SDK`_ software watchdog, which is designed to trigger an assert before an actual watchdog timeout. This enables the application to be able to collect coredump data before a reboot occurs. diff --git a/applications/asset_tracker_v2/doc/location_module.rst b/applications/asset_tracker_v2/doc/location_module.rst index 5c869bbf627..1470a4e51c6 100644 --- a/applications/asset_tracker_v2/doc/location_module.rst +++ b/applications/asset_tracker_v2/doc/location_module.rst @@ -67,26 +67,14 @@ Wi-Fi positioning Wi-Fi positioning is supported with an nRF7002 EK on the nRF91 Series DK. To enable Wi-Fi positioning and especially nRF7002 functionality, use the ``-DSHIELD=nrf7002ek`` and ``-DEXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf`` options. +The following is an example of the CLI command: -.. tabs:: +.. parsed-literal:: + :class: highlight - .. group-tab:: nRF9161 DK + west build -p -b *build_target* -- -DSHIELD=nrf7002ek -DEXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf - To build for the nRF9161 DK with nRF7002 EK, use the ``nrf9161dk_nrf9161_ns`` build target with the ``SHIELD`` CMake option set to ``nrf7002ek`` and a scan-only overlay configuration. - The following is an example of the CLI command: - - .. code-block:: console - - west build -p -b nrf9161dk_nrf9161_ns -- -DSHIELD=nrf7002ek -DEXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf - - .. group-tab:: nRF9160 DK - - To build for the nRF9160 DK with nRF7002 EK, use the ``nrf9160dk_nrf9160_ns`` build target with the ``SHIELD`` CMake option set to ``nrf7002ek`` and a scan-only overlay configuration. - The following is an example of the CLI command: - - .. code-block:: console - - west build -p -b nrf9160dk_nrf9160_ns -- -DSHIELD=nrf7002ek -DEXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf +Replace the *build_target* with the build target of the DK you are using (see :ref:`asset_tracker_v2_requirements`). Wi-Fi positioning has the following limitations: diff --git a/applications/asset_tracker_v2/doc/unit_test.rst b/applications/asset_tracker_v2/doc/unit_test.rst index 1af401e9927..c518c009b54 100644 --- a/applications/asset_tracker_v2/doc/unit_test.rst +++ b/applications/asset_tracker_v2/doc/unit_test.rst @@ -23,9 +23,9 @@ Running the unit test To run the unit test, you must navigate to the test directory of the respective internal module. For example, to run the unit test for :ref:`asset_tracker_v2_debug_module`, navigate to :file:`asset_tracker_v2/tests/debug_module`. -The unit tests can be executed using West or Twister. +The unit tests can be executed using west or Twister. -Running unit tests using West +Running unit tests using west ============================= Enter the following west commands to execute the tests on different board targets: diff --git a/applications/asset_tracker_v2/include/nrf9151dk_nrf9151_ns/led_state_def.h b/applications/asset_tracker_v2/include/nrf9151dk_nrf9151_ns/led_state_def.h new file mode 100644 index 00000000000..97dd963f89f --- /dev/null +++ b/applications/asset_tracker_v2/include/nrf9151dk_nrf9151_ns/led_state_def.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "events/led_state_event.h" + +/* This configuration file is included only once from led_state module and holds + * information about LED effects associated with Asset Tracker v2 states. + */ + +/* This structure enforces the header file to be included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} led_state_def_include_once; + +enum led_id { + LED_ID_1, + LED_ID_2, + LED_ID_3, + LED_ID_4, + + LED_ID_COUNT, + + LED_ID_CONNECTING = LED_ID_1, + LED_ID_CLOUD_CONNECTING = LED_ID_3, + LED_ID_SEARCHING = LED_ID_2, + LED_ID_PUBLISHING = LED_ID_3, + LED_ID_ASSOCIATING = LED_ID_3, + LED_ID_ASSOCIATED = LED_ID_3, + LED_ID_FOTA_1 = LED_ID_1, + LED_ID_FOTA_2 = LED_ID_2, + LED_ID_PASSIVE_MODE_1 = LED_ID_3, + LED_ID_PASSIVE_MODE_2 = LED_ID_4, + LED_ID_ACTIVE_MODE = LED_ID_4, +}; + +#define LED_PERIOD_NORMAL 350 +#define LED_PERIOD_RAPID 100 +#define LED_TICKS_DOUBLE 2 +#define LED_TICKS_TRIPLE 3 + +static const struct led_effect asset_tracker_led_effect[] = { + [LED_STATE_LTE_CONNECTING] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_LOCATION_SEARCHING] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_CLOUD_PUBLISHING] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_CLOUD_CONNECTING] = LED_EFFECT_LED_CLOCK(LED_TICKS_TRIPLE, + LED_COLOR(100, 100, 100)), + [LED_STATE_CLOUD_ASSOCIATING] = LED_EFFECT_LED_CLOCK(LED_TICKS_DOUBLE, + LED_COLOR(100, 100, 100)), + [LED_STATE_CLOUD_ASSOCIATED] = LED_EFFECT_LED_ON_GO_OFF(LED_COLOR(100, 100, 100), + LED_PERIOD_NORMAL, + LED_PERIOD_RAPID), + [LED_STATE_ACTIVE_MODE] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_PASSIVE_MODE] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_ERROR_SYSTEM_FAULT] = LED_EFFECT_LED_BLINK(LED_PERIOD_NORMAL, + LED_COLOR(100, 100, 100)), + [LED_STATE_FOTA_UPDATING] = LED_EFFECT_LED_BLINK(LED_PERIOD_RAPID, + LED_COLOR(100, 100, 100)), + [LED_STATE_FOTA_UPDATE_REBOOT] = LED_EFFECT_LED_ON(LED_COLOR(100, 100, 100)), + [LED_STATE_TURN_OFF] = LED_EFFECT_LED_OFF(), +}; diff --git a/applications/asset_tracker_v2/include/thingy91x_nrf9151_ns/led_state_def.h b/applications/asset_tracker_v2/include/thingy91x_nrf9151_ns/led_state_def.h new file mode 100644 index 00000000000..51a1953088c --- /dev/null +++ b/applications/asset_tracker_v2/include/thingy91x_nrf9151_ns/led_state_def.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "events/led_state_event.h" + +/* This configuration file is included only once from led_state module and holds + * information about LED effects associated with Asset Tracker v2 states. + */ + +/* This structure enforces the header file to be included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} led_state_def_include_once; + +enum led_id { + LED_ID_1, + LED_ID_COUNT, + LED_ID_CONNECTING = LED_ID_1, + LED_ID_CLOUD_CONNECTING = LED_ID_1, + LED_ID_SEARCHING = LED_ID_1, + LED_ID_PUBLISHING = LED_ID_1, + LED_ID_ASSOCIATING = LED_ID_1, + LED_ID_ASSOCIATED = LED_ID_1, + LED_ID_FOTA_1 = LED_ID_1, + LED_ID_FOTA_2 = LED_ID_1, + LED_ID_PASSIVE_MODE_1 = LED_ID_1, + LED_ID_PASSIVE_MODE_2 = LED_ID_1, + LED_ID_ACTIVE_MODE = LED_ID_1, +}; + +#define LED_PERIOD_NORMAL 350 +#define LED_PERIOD_RAPID 100 +#define LED_TICKS_DOUBLE 2 +#define LED_TICKS_TRIPLE 3 + +static const struct led_effect asset_tracker_led_effect[] = { + [LED_STATE_LTE_CONNECTING] = LED_EFFECT_LED_BREATH(LED_PERIOD_NORMAL, + LED_COLOR(255, 255, 0)), + [LED_STATE_LOCATION_SEARCHING] = LED_EFFECT_LED_BREATH(LED_PERIOD_NORMAL, + LED_COLOR(255, 0, 255)), + [LED_STATE_CLOUD_PUBLISHING] = LED_EFFECT_LED_BREATH(LED_PERIOD_NORMAL, + LED_COLOR(0, 255, 0)), + [LED_STATE_CLOUD_CONNECTING] = LED_EFFECT_LED_CLOCK(LED_TICKS_TRIPLE, + LED_COLOR(0, 255, 0)), + [LED_STATE_CLOUD_ASSOCIATING] = LED_EFFECT_LED_CLOCK(LED_TICKS_DOUBLE, + LED_COLOR(255, 255, 255)), + [LED_STATE_CLOUD_ASSOCIATED] = LED_EFFECT_LED_ON_GO_OFF(LED_COLOR(255, 255, 255), + LED_PERIOD_NORMAL, + LED_PERIOD_RAPID), + [LED_STATE_ACTIVE_MODE] = LED_EFFECT_LED_BREATH(LED_PERIOD_NORMAL, + LED_COLOR(0, 255, 255)), + [LED_STATE_PASSIVE_MODE] = LED_EFFECT_LED_BREATH(LED_PERIOD_NORMAL, + LED_COLOR(0, 0, 255)), + [LED_STATE_ERROR_SYSTEM_FAULT] = LED_EFFECT_LED_ON(LED_COLOR(255, 0, 0)), + [LED_STATE_FOTA_UPDATING] = LED_EFFECT_LED_BREATH(LED_PERIOD_RAPID, + LED_COLOR(255, 165, 0)), + [LED_STATE_FOTA_UPDATE_REBOOT] = LED_EFFECT_LED_ON(LED_COLOR(255, 165, 0)), + [LED_STATE_TURN_OFF] = LED_EFFECT_LED_OFF(), +}; diff --git a/applications/asset_tracker_v2/overlay-carrier.conf b/applications/asset_tracker_v2/overlay-carrier.conf index b5ce5b215f9..025cd469f81 100644 --- a/applications/asset_tracker_v2/overlay-carrier.conf +++ b/applications/asset_tracker_v2/overlay-carrier.conf @@ -30,3 +30,6 @@ CONFIG_MPU_ALLOW_FLASH_WRITE=y # Default partition for NVS is unused CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0 + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/applications/asset_tracker_v2/overlay-lwm2m.conf b/applications/asset_tracker_v2/overlay-lwm2m.conf index 13539be6fe7..e14d143165d 100644 --- a/applications/asset_tracker_v2/overlay-lwm2m.conf +++ b/applications/asset_tracker_v2/overlay-lwm2m.conf @@ -26,24 +26,64 @@ CONFIG_LWM2M_RW_SENML_CBOR_RECORDS=45 CONFIG_ZCBOR=y CONFIG_ZCBOR_CANONICAL=y -# Enable TLS session caching to prevent doing a full TLS handshake for every send. +# Enable DTLS Connection Identifier and TLS session caching +# to prevent doing a full TLS handshake for every send. CONFIG_LWM2M_TLS_SESSION_CACHING=y +CONFIG_LWM2M_DTLS_CID=y -# Set uptime to once every 12 hours. +# Set uptime to 12 hours. +# Update every 60 minutes (3600 s) CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=43200 +CONFIG_LWM2M_UPDATE_PERIOD=3600 +CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=60 # LwM2M Queue Mode CONFIG_LWM2M_QUEUE_MODE_ENABLED=y -CONFIG_LWM2M_RD_CLIENT_SUSPEND_SOCKET_AT_IDLE=y +CONFIG_LWM2M_RD_CLIENT_STOP_POLLING_AT_IDLE=y # Sets the duration that the lwm2m engine will be polling for data after transmission before # the socket is closed. CONFIG_LWM2M_QUEUE_MODE_UPTIME=30 -## Set Requested Active Time (RAT) to 60 seconds. Preferably a little bit longer than the -## configured LWM2M_QUEUE_MODE_UPTIME. Due to NAT/firewall UDP connections are usually -## closed within 30-60 seconds so there is in general no point in setting a longer -## Queue mode uptime / LTE PSM active time. -CONFIG_LTE_PSM_REQ_RAT="00100001" +# Configure PSM mode +CONFIG_LTE_PSM_REQ=y +# Request periodic TAU of 3600 seconds (60 minutes) +CONFIG_LTE_PSM_REQ_RPTAU="00000110" + +# Set Requested Active Time (RAT) to 30 seconds. Preferably same as the +# configured LWM2M_QUEUE_MODE_UPTIME. Due to NAT/firewall UDP connections are usually +# closed within 30-60 seconds so there is in general no point in setting a longer +# Queue mode uptime / LTE PSM active time. +CONFIG_LTE_PSM_REQ_RAT="00001111" + +# Request eDRX mode +CONFIG_LTE_EDRX_REQ=y + +# Requested eDRX cycle length for LTE-M and NB-IoT +# This should be fine-tuned for the network and the chosen server. +# Lowest value is the most responsive, but uses more energy during the active eDRX period. +# Longer period may cause more CoAP packet drops on server requests. +# "0000" is 5.12 s +# "0001" is 10.24 s +# "0010" is 20.48 s. +CONFIG_LTE_EDRX_REQ_VALUE_LTE_M="0000" +CONFIG_LTE_EDRX_REQ_VALUE_NBIOT="0000" + +# Request Paging time window of 1.28 seconds for LTE-M +CONFIG_LTE_PTW_VALUE_LTE_M="0000" + +# Request Paging time window of 2.56 seconds for NB-IoT +CONFIG_LTE_PTW_VALUE_NBIOT="0000" + +# Get notification before Tracking Area Update (TAU). Notification triggers registration +# update and TAU will be sent with the update which decreases power consumption. +CONFIG_LTE_LC_TAU_PRE_WARNING_NOTIFICATIONS=y + +# Optimize powersaving by using tickless mode in LwM2M engine +CONFIG_NET_SOCKETPAIR=y +CONFIG_LWM2M_TICKLESS=y + +# Enable Release Assistance Indication +CONFIG_LWM2M_CLIENT_UTILS_RAI=y # Use LwM2M client bootstrap server. # CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP=y @@ -66,7 +106,7 @@ CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 # IPSO v1.1 CONFIG_LWM2M_IPSO_SUPPORT=y CONFIG_LWM2M_IPSO_PUSH_BUTTON_VERSION_1_1=y -CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_2=y +CONFIG_LWM2M_CONNMON_OBJECT_VERSION_1_3=y # Zephyr LwM2M standard objects CONFIG_LWM2M_IPSO_PUSH_BUTTON=y diff --git a/applications/asset_tracker_v2/overlay-memfault.conf b/applications/asset_tracker_v2/overlay-memfault.conf index 61f5fc0e281..3fd47d59fc9 100644 --- a/applications/asset_tracker_v2/overlay-memfault.conf +++ b/applications/asset_tracker_v2/overlay-memfault.conf @@ -6,6 +6,7 @@ CONFIG_MEMFAULT=y CONFIG_MEMFAULT_NCS_PROJECT_KEY="" +CONFIG_MEMFAULT_NCS_DEVICE_ID_IMEI=y CONFIG_MEMFAULT_NCS_LTE_METRICS=y CONFIG_MEMFAULT_NCS_STACK_METRICS=y CONFIG_MEMFAULT_LOGGING_ENABLE=y diff --git a/applications/asset_tracker_v2/pm_static_nrf9151dk_nrf9151_ns.yml b/applications/asset_tracker_v2/pm_static_nrf9151dk_nrf9151_ns.yml new file mode 100644 index 00000000000..d9024b43707 --- /dev/null +++ b/applications/asset_tracker_v2/pm_static_nrf9151dk_nrf9151_ns.yml @@ -0,0 +1,4 @@ +mcuboot_secondary: + region: external_flash + address: 0x0 + size: 0xD0000 diff --git a/applications/asset_tracker_v2/sample.yaml b/applications/asset_tracker_v2/sample.yaml index 06fafd4377e..cd17eb41f7c 100644 --- a/applications/asset_tracker_v2/sample.yaml +++ b/applications/asset_tracker_v2/sample.yaml @@ -4,7 +4,13 @@ tests: applications.asset_tracker_v2.nrf_cloud: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns native_sim + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + - native_sim integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -14,7 +20,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -22,7 +31,12 @@ tests: applications.asset_tracker_v2.nrf_cloud-pgps: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -32,7 +46,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -41,7 +58,12 @@ tests: applications.asset_tracker_v2.nrf_cloud-no-agnss: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -51,7 +73,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -60,7 +85,13 @@ tests: applications.asset_tracker_v2.aws: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns native_sim + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + - native_sim integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -73,7 +104,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -84,7 +118,12 @@ tests: applications.asset_tracker_v2.aws-pgps: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -96,7 +135,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -107,7 +149,12 @@ tests: applications.asset_tracker_v2.aws-all: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -121,7 +168,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -134,7 +184,13 @@ tests: applications.asset_tracker_v2.azure: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns native_sim + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + - native_sim integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -148,7 +204,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -160,7 +219,13 @@ tests: applications.asset_tracker_v2.debug: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns native_sim + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + - native_sim integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -171,7 +236,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -180,7 +248,12 @@ tests: applications.asset_tracker_v2.debug-memfault: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -192,7 +265,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -203,7 +279,12 @@ tests: applications.asset_tracker_v2.memfault: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -215,7 +296,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -226,7 +310,12 @@ tests: applications.asset_tracker_v2.low-power: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -236,7 +325,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -245,7 +337,10 @@ tests: applications.asset_tracker_v2.carrier.nrf9160dk: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns extra_args: EXTRA_CONF_FILE=overlay-carrier.conf @@ -254,7 +349,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -268,10 +366,23 @@ tests: - nrf9161dk_nrf9161_ns extra_args: EXTRA_CONF_FILE=overlay-carrier.conf tags: ci_build + applications.asset_tracker_v2.carrier.nrf9151dk: + build_only: true + build_on_all: true + platform_allow: nrf9151dk_nrf9151_ns + integration_platforms: + - nrf9151dk_nrf9151_ns + extra_args: EXTRA_CONF_FILE=overlay-carrier.conf + tags: ci_build applications.asset_tracker_v2.lwm2m.bootstrap-low_power: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -283,7 +394,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -292,7 +406,12 @@ tests: applications.asset_tracker_v2.lwm2m.debug: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -302,7 +421,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -311,10 +433,12 @@ tests: applications.asset_tracker_v2.lwm2m.debug-modem_trace: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - - thingy91_nrf9160_ns extra_args: EXTRA_CONF_FILE="overlay-lwm2m.conf;overlay-debug.conf" SNIPPET="nrf91-modem-trace-uart;tfm-enable-share-uart" @@ -323,21 +447,58 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns integration_platforms: - nrf9160dk_nrf9160_ns - - thingy91_nrf9160_ns extra_args: > EXTRA_CONF_FILE="overlay-lwm2m.conf;overlay-debug.conf" asset_tracker_v2_SNIPPET="nrf91-modem-trace-uart;tfm-enable-share-uart" tags: ci_build sysbuild + applications.asset_tracker_v2.lwm2m.modem_trace: + build_only: true + build_on_all: true + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + integration_platforms: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + extra_args: + EXTRA_CONF_FILE="overlay-lwm2m.conf" + SNIPPET="nrf91-modem-trace-uart;tfm-enable-share-uart" + tags: ci_build + applications.asset_tracker_v2.lwm2m.modem_trace.sysbuild: + build_only: true + sysbuild: true + build_on_all: true + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns + integration_platforms: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + extra_args: > + EXTRA_CONF_FILE="overlay-lwm2m.conf" + asset_tracker_v2_SNIPPET="nrf91-modem-trace-uart;tfm-enable-share-uart" + tags: ci_build sysbuild applications.asset_tracker_v2.lwm2m.memfault: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns - thingy91_nrf9160_ns extra_configs: - CONFIG_MEMFAULT_NCS_PROJECT_KEY="PROJECTKEY" @@ -347,7 +508,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -358,10 +522,16 @@ tests: applications.asset_tracker_v2.memfault-low-power: build_only: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns - thingy91_nrf9160_ns extra_configs: - CONFIG_MEMFAULT_NCS_PROJECT_KEY="PROJECTKEY" @@ -371,7 +541,10 @@ tests: build_only: true sysbuild: true build_on_all: true - platform_allow: nrf9160dk_nrf9160_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - thingy91_nrf9160_ns @@ -401,12 +574,23 @@ tests: platform_allow: nrf9161dk_nrf9161_ns extra_args: SHIELD=nrf7002ek EXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf tags: ci_build + applications.asset_tracker_v2.nrf7002ek_wifi.nrf9151dk: + build_only: true + integration_platforms: + - nrf9151dk_nrf9151_ns + platform_allow: nrf9151dk_nrf9151_ns + extra_args: SHIELD=nrf7002ek EXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf + tags: ci_build applications.asset_tracker_v2.nrf7002ek_wifi-debug: build_only: true integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns extra_args: SHIELD=nrf7002ek EXTRA_CONF_FILE="overlay-nrf7002ek-wifi-scan-only.conf;overlay-debug.conf" tags: ci_build diff --git a/applications/asset_tracker_v2/src/cloud-certs/ca-cert.pem b/applications/asset_tracker_v2/src/cloud-certs/ca-cert.pem deleted file mode 100644 index 0d6eaa7df0b..00000000000 --- a/applications/asset_tracker_v2/src/cloud-certs/ca-cert.pem +++ /dev/null @@ -1,3 +0,0 @@ -"-----BEGIN CA CERTIFICATE-----\n" -"-----CERTIFICATE-----\n" -"-----END CA CERTIFICATE-----\n" diff --git a/applications/asset_tracker_v2/src/cloud-certs/client-cert.pem b/applications/asset_tracker_v2/src/cloud-certs/client-cert.pem deleted file mode 100644 index 0ee47f337c8..00000000000 --- a/applications/asset_tracker_v2/src/cloud-certs/client-cert.pem +++ /dev/null @@ -1,3 +0,0 @@ -"-----BEGIN CLIENT CERTIFICATE-----\n" -"-----CERTIFICATE-----\n" -"-----END CLIENT CERTIFICATE-----\n" diff --git a/applications/asset_tracker_v2/src/cloud-certs/private-key.pem b/applications/asset_tracker_v2/src/cloud-certs/private-key.pem deleted file mode 100644 index 18bee64d9cb..00000000000 --- a/applications/asset_tracker_v2/src/cloud-certs/private-key.pem +++ /dev/null @@ -1,3 +0,0 @@ -"-----BEGIN PRIVATE KEY-----\n" -"-----KEY-----\n" -"-----END PRIVATE KEY-----\n" diff --git a/applications/asset_tracker_v2/src/cloud/aws_iot_integration.c b/applications/asset_tracker_v2/src/cloud/aws_iot_integration.c index 1e2cb665663..7b9160867d7 100644 --- a/applications/asset_tracker_v2/src/cloud/aws_iot_integration.c +++ b/applications/asset_tracker_v2/src/cloud/aws_iot_integration.c @@ -21,31 +21,26 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_CLOUD_INTEGRATION_LOG_LEVEL); #endif #define AWS "$aws/things/" -#define AWS_LEN (sizeof(AWS) - 1) #define CFG_TOPIC AWS "%s/shadow/get/accepted/desired/cfg" -#define CFG_TOPIC_LEN (AWS_LEN + AWS_CLOUD_CLIENT_ID_LEN + 32) +#define CFG_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(CFG_TOPIC) - 3) #define BATCH_TOPIC "%s/batch" -#define BATCH_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 6) +#define BATCH_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(BATCH_TOPIC) - 3) #define MESSAGES_TOPIC "%s/messages" -#define MESSAGES_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 9) +#define MESSAGES_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(MESSAGES_TOPIC) - 3) #define GROUND_FIX_TOPIC "%s/ground-fix" -#define GROUND_FIX_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 11) -#define AGNSS_REQUEST_TOPIC "%s/agps/get" -#define AGNSS_REQUEST_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 9) -#define AGNSS_RESPONSE_TOPIC "%s/agps" -#define AGNSS_RESPONSE_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 5) +#define GROUND_FIX_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(GROUND_FIX_TOPIC) - 3) +#define AGNSS_REQUEST_TOPIC "%s/agnss/get" +#define AGNSS_REQUEST_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(AGNSS_REQUEST_TOPIC) - 3) +#define AGNSS_RESPONSE_TOPIC "%s/agnss" +#define AGNSS_RESPONSE_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(AGNSS_RESPONSE_TOPIC) - 3) #define PGPS_REQUEST_TOPIC "%s/pgps/get" -#define PGPS_REQUEST_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 9) +#define PGPS_REQUEST_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(PGPS_REQUEST_TOPIC) - 3) #define PGPS_RESPONSE_TOPIC "%s/pgps" -#define PGPS_RESPONSE_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 5) +#define PGPS_RESPONSE_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(PGPS_RESPONSE_TOPIC) - 3) #define MEMFAULT_TOPIC "%s/memfault" \ IF_ENABLED(CONFIG_DEBUG_MODULE_MEMFAULT_USE_EXTERNAL_TRANSPORT, \ ("/" CONFIG_MEMFAULT_NCS_PROJECT_KEY)) -#if defined(CONFIG_DEBUG_MODULE_MEMFAULT_USE_EXTERNAL_TRANSPORT) -#define MEMFAULT_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 9 + sizeof(CONFIG_MEMFAULT_NCS_PROJECT_KEY)) -#else -#define MEMFAULT_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + 9) -#endif /* if defined(CONFIG_DEBUG_MODULE_MEMFAULT_USE_EXTERNAL_TRANSPORT) */ +#define MEMFAULT_TOPIC_LEN (AWS_CLOUD_CLIENT_ID_LEN + sizeof(MEMFAULT_TOPIC) - 3) #define APP_SUB_TOPIC_IDX_CFG 0 #define APP_SUB_TOPIC_IDX_AGNSS 1 @@ -153,8 +148,8 @@ static int populate_app_endpoint_topics(void) sub_topics[APP_SUB_TOPIC_IDX_CFG].topic.utf8 = cfg_topic; sub_topics[APP_SUB_TOPIC_IDX_CFG].topic.size = CFG_TOPIC_LEN; - err = snprintf(agnss_response_topic, sizeof(agnss_response_topic), AGNSS_RESPONSE_TOPIC, - client_id_buf); + err = snprintf(agnss_response_topic, sizeof(agnss_response_topic), + AGNSS_RESPONSE_TOPIC, client_id_buf); if (err != AGNSS_RESPONSE_TOPIC_LEN) { return -ENOMEM; } @@ -517,7 +512,7 @@ int cloud_wrap_agnss_request_send(char *buf, size_t len, bool ack, uint32_t id) .len = len, .message_id = id, .qos = ack ? MQTT_QOS_1_AT_LEAST_ONCE : MQTT_QOS_0_AT_MOST_ONCE, - /* /agps/get */ + /* /agnss/get */ .topic.str = pub_topics[APP_PUB_TOPIC_IDX_AGNSS].topic.utf8, .topic.len = pub_topics[APP_PUB_TOPIC_IDX_AGNSS].topic.size }; diff --git a/applications/asset_tracker_v2/src/cloud/azure_iot_hub_integration.c b/applications/asset_tracker_v2/src/cloud/azure_iot_hub_integration.c index 64a9bd20df3..56667de9d7f 100644 --- a/applications/asset_tracker_v2/src/cloud/azure_iot_hub_integration.c +++ b/applications/asset_tracker_v2/src/cloud/azure_iot_hub_integration.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_CLOUD_INTEGRATION_LOG_LEVEL); #define PROP_BAG_BATCH_KEY "batch" #define PROP_BAG_GROUND_FIX_KEY "ground-fix" -#define PROP_BAG_AGNSS_KEY "agps" +#define PROP_BAG_AGNSS_KEY "agnss" #define PROP_BAG_AGNSS_GET_VALUE "get" #define PROP_BAG_AGNSS_RESPONSE_VALUE "result" diff --git a/applications/asset_tracker_v2/src/cloud/cloud_codec/cloud_codec.h b/applications/asset_tracker_v2/src/cloud/cloud_codec/cloud_codec.h index 58ce7427db0..54a83b13bb4 100644 --- a/applications/asset_tracker_v2/src/cloud/cloud_codec/cloud_codec.h +++ b/applications/asset_tracker_v2/src/cloud/cloud_codec/cloud_codec.h @@ -38,6 +38,11 @@ extern "C" { #endif +/** Heading accuracy limit for the heading to be considered valid. Heading is only sent to the + * cloud if it is accurate enough. + */ +#define CLOUD_GNSS_HEADING_ACC_LIMIT (float)60.0 + /** @brief Structure containing battery data published to cloud. */ struct cloud_data_battery { /** Battery fuel gauge percentage. */ @@ -49,18 +54,24 @@ struct cloud_data_battery { }; struct cloud_data_gnss_pvt { - /** Longitude. */ - double longi; /** Latitude. */ double lat; + /** Longitude. */ + double lon; + /** Position accuracy in (2D 1-sigma) in meters. */ + float acc; /** Altitude above WGS-84 ellipsoid in meters. */ float alt; - /** Accuracy in (2D 1-sigma) in meters. */ - float acc; - /** Horizontal speed in meters. */ + /** Altitude accuracy (1-sigma) in meters. */ + float alt_acc; + /** Horizontal speed in m/s. */ float spd; + /** Horizontal speed accuracy (1-sigma) in m/s. */ + float spd_acc; /** Heading of movement in degrees. */ float hdg; + /** Heading of movement accuracy (1-sigma) in degrees. */ + float hdg_acc; }; /** @brief Structure containing GNSS data published to cloud. */ diff --git a/applications/asset_tracker_v2/src/cloud/cloud_codec/json_common.c b/applications/asset_tracker_v2/src/cloud/cloud_codec/json_common.c index f2e310f0fd8..1c194fecbff 100644 --- a/applications/asset_tracker_v2/src/cloud/cloud_codec/json_common.c +++ b/applications/asset_tracker_v2/src/cloud/cloud_codec/json_common.c @@ -350,13 +350,13 @@ int json_common_gnss_data_add(cJSON *parent, goto exit; } - err = json_add_number(gnss_val_obj, DATA_GNSS_LONGITUDE, data->pvt.longi); + err = json_add_number(gnss_val_obj, DATA_GNSS_LATITUDE, data->pvt.lat); if (err) { LOG_ERR("Encoding error: %d returned at %s:%d", err, __FILE__, __LINE__); goto exit; } - err = json_add_number(gnss_val_obj, DATA_GNSS_LATITUDE, data->pvt.lat); + err = json_add_number(gnss_val_obj, DATA_GNSS_LONGITUDE, data->pvt.lon); if (err) { LOG_ERR("Encoding error: %d returned at %s:%d", err, __FILE__, __LINE__); goto exit; @@ -380,10 +380,12 @@ int json_common_gnss_data_add(cJSON *parent, goto exit; } - err = json_add_number(gnss_val_obj, DATA_GNSS_HEADING, data->pvt.hdg); - if (err) { - LOG_ERR("Encoding error: %d returned at %s:%d", err, __FILE__, __LINE__); - goto exit; + if (data->pvt.hdg_acc < CLOUD_GNSS_HEADING_ACC_LIMIT) { + err = json_add_number(gnss_val_obj, DATA_GNSS_HEADING, data->pvt.hdg); + if (err) { + LOG_ERR("Encoding error: %d returned at %s:%d", err, __FILE__, __LINE__); + goto exit; + } } json_add_obj(gnss_obj, DATA_VALUE, gnss_val_obj); diff --git a/applications/asset_tracker_v2/src/cloud/cloud_codec/lwm2m/lwm2m_codec_helpers.c b/applications/asset_tracker_v2/src/cloud/cloud_codec/lwm2m/lwm2m_codec_helpers.c index fd91b3dfe22..63006e91648 100644 --- a/applications/asset_tracker_v2/src/cloud/cloud_codec/lwm2m/lwm2m_codec_helpers.c +++ b/applications/asset_tracker_v2/src/cloud/cloud_codec/lwm2m/lwm2m_codec_helpers.c @@ -240,6 +240,33 @@ int lwm2m_codec_helpers_setup_resources(void) return err; } + err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MODEL_NUMBER_RID), + CONFIG_BOARD, + (uint16_t)sizeof(CONFIG_BOARD), + (uint16_t)sizeof(CONFIG_BOARD), + LWM2M_RES_DATA_FLAG_RO); + if (err) { + return err; + } + + err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, HARDWARE_VERSION_RID), + CONFIG_SOC, + (uint16_t)sizeof(CONFIG_SOC), + (uint16_t)sizeof(CONFIG_SOC), + LWM2M_RES_DATA_FLAG_RO); + if (err) { + return err; + } + + err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MANUFACTURER_RID), + CONFIG_CLOUD_CODEC_MANUFACTURER, + (uint16_t)sizeof(CONFIG_CLOUD_CODEC_MANUFACTURER), + (uint16_t)sizeof(CONFIG_CLOUD_CODEC_MANUFACTURER), + LWM2M_RES_DATA_FLAG_RO); + if (err) { + return err; + } + #if defined(CONFIG_CLOUD_CODEC_LWM2M_THINGY91_SENSORS) err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_PRESSURE_ID, 0, TIMESTAMP_RID), &pressure_ts, sizeof(pressure_ts), @@ -263,23 +290,23 @@ int lwm2m_codec_helpers_setup_resources(void) } err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_TEMP_SENSOR_ID, 0, SENSOR_UNITS_RID), - BME680_TEMP_UNIT, (uint16_t)strlen(BME680_TEMP_UNIT), - (uint16_t)strlen(BME680_TEMP_UNIT), LWM2M_RES_DATA_FLAG_RO); + BME680_TEMP_UNIT, (uint16_t)strlen(BME680_TEMP_UNIT) + 1, + (uint16_t)strlen(BME680_TEMP_UNIT) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; } err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_HUMIDITY_SENSOR_ID, 0, SENSOR_UNITS_RID), - BME680_HUMID_UNIT, (uint16_t)strlen(BME680_HUMID_UNIT), - (uint16_t)strlen(BME680_HUMID_UNIT), + BME680_HUMID_UNIT, (uint16_t)strlen(BME680_HUMID_UNIT) + 1, + (uint16_t)strlen(BME680_HUMID_UNIT) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; } err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_PRESSURE_ID, 0, SENSOR_UNITS_RID), - BME680_PRESSURE_UNIT, (uint16_t)strlen(BME680_PRESSURE_UNIT), - (uint16_t)strlen(BME680_PRESSURE_UNIT), + BME680_PRESSURE_UNIT, (uint16_t)strlen(BME680_PRESSURE_UNIT) + 1, + (uint16_t)strlen(BME680_PRESSURE_UNIT) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; @@ -293,8 +320,8 @@ int lwm2m_codec_helpers_setup_resources(void) err = lwm2m_set_res_buf( &LWM2M_OBJ(IPSO_OBJECT_PUSH_BUTTON_ID, BUTTON1_OBJ_INST_ID, APPLICATION_TYPE_RID), - BUTTON1_APP_NAME, (uint16_t)strlen(BUTTON1_APP_NAME), - (uint16_t)strlen(BUTTON1_APP_NAME), LWM2M_RES_DATA_FLAG_RO); + BUTTON1_APP_NAME, (uint16_t)strlen(BUTTON1_APP_NAME) + 1, + (uint16_t)strlen(BUTTON1_APP_NAME) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; } @@ -307,12 +334,11 @@ int lwm2m_codec_helpers_setup_resources(void) } if (CONFIG_LWM2M_IPSO_PUSH_BUTTON_INSTANCE_COUNT == 2) { - err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_PUSH_BUTTON_ID, - BUTTON2_OBJ_INST_ID, - APPLICATION_TYPE_RID), - BUTTON2_APP_NAME, (uint16_t)strlen(BUTTON2_APP_NAME), - (uint16_t)strlen(BUTTON2_APP_NAME), - LWM2M_RES_DATA_FLAG_RO); + err = lwm2m_set_res_buf(&LWM2M_OBJ(IPSO_OBJECT_PUSH_BUTTON_ID, BUTTON2_OBJ_INST_ID, + APPLICATION_TYPE_RID), + BUTTON2_APP_NAME, (uint16_t)strlen(BUTTON2_APP_NAME) + 1, + (uint16_t)strlen(BUTTON2_APP_NAME) + 1, + LWM2M_RES_DATA_FLAG_RO); if (err) { return err; } @@ -597,7 +623,7 @@ int lwm2m_codec_helpers_set_gnss_data(struct cloud_data_gnss *gnss) } err = lwm2m_set_f64(&LWM2M_OBJ(LWM2M_OBJECT_LOCATION_ID, 0, LONGITUDE_RID), - gnss->pvt.longi); + gnss->pvt.lon); if (err) { return err; } @@ -669,8 +695,8 @@ int lwm2m_codec_helpers_set_modem_dynamic_data(struct cloud_data_modem_dynamic * err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID, 0, IP_ADDRESSES, 0), - modem_dynamic->ip, (uint16_t)strlen(modem_dynamic->ip), - (uint16_t)strlen(modem_dynamic->ip), + modem_dynamic->ip, (uint16_t)strlen(modem_dynamic->ip) + 1, + (uint16_t)strlen(modem_dynamic->ip) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; @@ -678,8 +704,8 @@ int lwm2m_codec_helpers_set_modem_dynamic_data(struct cloud_data_modem_dynamic * err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID, 0, APN, 0), - modem_dynamic->apn, (uint16_t)strlen(modem_dynamic->apn), - (uint16_t)strlen(modem_dynamic->apn), + modem_dynamic->apn, (uint16_t)strlen(modem_dynamic->apn) + 1, + (uint16_t)strlen(modem_dynamic->apn) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; @@ -737,37 +763,10 @@ int lwm2m_codec_helpers_set_modem_static_data(struct cloud_data_modem_static *mo return -ENODATA; } - err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MODEL_NUMBER_RID), - CONFIG_BOARD, - (uint16_t)strlen(CONFIG_BOARD), - (uint16_t)strlen(CONFIG_BOARD), - LWM2M_RES_DATA_FLAG_RO); - if (err) { - return err; - } - - err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, HARDWARE_VERSION_RID), - CONFIG_SOC, - (uint16_t)strlen(CONFIG_SOC), - (uint16_t)strlen(CONFIG_SOC), - LWM2M_RES_DATA_FLAG_RO); - if (err) { - return err; - } - - err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MANUFACTURER_RID), - CONFIG_CLOUD_CODEC_MANUFACTURER, - (uint16_t)strlen(CONFIG_CLOUD_CODEC_MANUFACTURER), - (uint16_t)strlen(CONFIG_CLOUD_CODEC_MANUFACTURER), - LWM2M_RES_DATA_FLAG_RO); - if (err) { - return err; - } - err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, FIRMWARE_VERSION_RID), modem_static->appv, - (uint16_t)strlen(modem_static->appv), - (uint16_t)strlen(modem_static->appv), + (uint16_t)strlen(modem_static->appv) + 1, + (uint16_t)strlen(modem_static->appv) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; @@ -775,8 +774,8 @@ int lwm2m_codec_helpers_set_modem_static_data(struct cloud_data_modem_static *mo err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, SOFTWARE_VERSION_RID), modem_static->fw, - (uint16_t)strlen(modem_static->fw), - (uint16_t)strlen(modem_static->fw), + (uint16_t)strlen(modem_static->fw) + 1, + (uint16_t)strlen(modem_static->fw) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; @@ -785,8 +784,8 @@ int lwm2m_codec_helpers_set_modem_static_data(struct cloud_data_modem_static *mo err = lwm2m_set_res_buf(&LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_SERIAL_NUMBER_ID), modem_static->imei, - (uint16_t)strlen(modem_static->imei), - (uint16_t)strlen(modem_static->imei), + (uint16_t)strlen(modem_static->imei) + 1, + (uint16_t)strlen(modem_static->imei) + 1, LWM2M_RES_DATA_FLAG_RO); if (err) { return err; diff --git a/applications/asset_tracker_v2/src/cloud/cloud_codec/nrf_cloud/nrf_cloud_codec.c b/applications/asset_tracker_v2/src/cloud/cloud_codec/nrf_cloud/nrf_cloud_codec.c index d5c3c636308..dca50e1358e 100644 --- a/applications/asset_tracker_v2/src/cloud/cloud_codec/nrf_cloud/nrf_cloud_codec.c +++ b/applications/asset_tracker_v2/src/cloud/cloud_codec/nrf_cloud/nrf_cloud_codec.c @@ -156,15 +156,15 @@ static int add_pvt_data(cJSON *parent, struct cloud_data_gnss *gnss) .type = NRF_CLOUD_GNSS_TYPE_PVT, .ts_ms = NRF_CLOUD_NO_TIMESTAMP, .pvt = { - .lon = gnss->pvt.longi, .lat = gnss->pvt.lat, + .lon = gnss->pvt.lon, .accuracy = gnss->pvt.acc, .alt = gnss->pvt.alt, .has_alt = 1, .speed = gnss->pvt.spd, .has_speed = 1, .heading = gnss->pvt.hdg, - .has_heading = 1 + .has_heading = gnss->pvt.hdg_acc < CLOUD_GNSS_HEADING_ACC_LIMIT ? 1 : 0 } }; cJSON *data_obj = cJSON_CreateObject(); @@ -736,7 +736,7 @@ int cloud_codec_encode_cloud_location( #else NULL, #endif - true); + NULL); if (err) { LOG_ERR("nrf_cloud_location_request_msg_json_encode, error: %d", err); goto exit; diff --git a/applications/asset_tracker_v2/src/cloud/lwm2m_integration/lwm2m_integration.c b/applications/asset_tracker_v2/src/cloud/lwm2m_integration/lwm2m_integration.c index 620eaff778e..08438396c46 100644 --- a/applications/asset_tracker_v2/src/cloud/lwm2m_integration/lwm2m_integration.c +++ b/applications/asset_tracker_v2/src/cloud/lwm2m_integration/lwm2m_integration.c @@ -109,6 +109,8 @@ static void rd_client_event(struct lwm2m_ctx *client, enum lwm2m_rd_client_event struct cloud_wrap_event cloud_wrap_evt = { 0 }; bool notify = false; + lwm2m_utils_connection_manage(client, &client_event); + switch (client_event) { case LWM2M_RD_CLIENT_EVENT_NONE: LOG_DBG("LWM2M_RD_CLIENT_EVENT_NONE"); diff --git a/applications/asset_tracker_v2/src/events/app_module_event.h b/applications/asset_tracker_v2/src/events/app_module_event.h index fed3889f197..8feb1ab5054 100644 --- a/applications/asset_tracker_v2/src/events/app_module_event.h +++ b/applications/asset_tracker_v2/src/events/app_module_event.h @@ -34,7 +34,7 @@ enum app_module_event_type { APP_EVT_LTE_DISCONNECT, /** Signal other modules to start sampling and report the data when - * it's ready. + * it is ready. * The event must also contain a list with requested data types, * @ref app_module_data_type. */ diff --git a/applications/asset_tracker_v2/src/events/location_module_event.h b/applications/asset_tracker_v2/src/events/location_module_event.h index cc2f86a8e83..9a7d094b10c 100644 --- a/applications/asset_tracker_v2/src/events/location_module_event.h +++ b/applications/asset_tracker_v2/src/events/location_module_event.h @@ -94,23 +94,32 @@ enum location_module_event_type { /** @brief Position, velocity and time (PVT) data. */ struct location_module_pvt { + /** Latitude in degrees. */ + double latitude; + /** Longitude in degrees. */ double longitude; - /** Latitude in degrees. */ - double latitude; + /** Position accuracy (2D 1-sigma) in meters. */ + float accuracy; /** Altitude above WGS-84 ellipsoid in meters. */ float altitude; - /** Position accuracy (2D 1-sigma) in meters. */ - float accuracy; + /** Altitude accuracy in meters. */ + float altitude_accuracy; /** Horizontal speed in m/s. */ float speed; + /** Horizontal speed accuracy (1-sigma) in m/s. */ + float speed_accuracy; + /** Heading of user movement in degrees. */ float heading; + + /** Heading of user movement accuracy (1-sigma) in degrees. */ + float heading_accuracy; }; /** @brief Location module data for neighbor cells. */ diff --git a/applications/asset_tracker_v2/src/ext_sensors/ext_sensors.c b/applications/asset_tracker_v2/src/ext_sensors/ext_sensors.c index f070f2e2d78..b4b38581dfb 100644 --- a/applications/asset_tracker_v2/src/ext_sensors/ext_sensors.c +++ b/applications/asset_tracker_v2/src/ext_sensors/ext_sensors.c @@ -20,45 +20,89 @@ #include LOG_MODULE_REGISTER(ext_sensors, CONFIG_EXTERNAL_SENSORS_LOG_LEVEL); +struct env_sensor { + enum sensor_channel channel; + const struct device *dev; + struct k_spinlock lock; +}; + +#if defined(CONFIG_ADXL362) /* Convert to s/m2 depending on the maximum measured range used for adxl362. */ #if IS_ENABLED(CONFIG_ADXL362_ACCEL_RANGE_2G) -#define ADXL362_RANGE_MAX_M_S2 19.6133 +#define ACCEL_LP_RANGE_MAX_M_S2 19.6133 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_RANGE_4G) -#define ADXL362_RANGE_MAX_M_S2 39.2266 +#define ACCEL_LP_RANGE_MAX_M_S2 39.2266 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_RANGE_8G) -#define ADXL362_RANGE_MAX_M_S2 78.4532 +#define ACCEL_LP_RANGE_MAX_M_S2 78.4532 #endif /* This is derived from the sensitivity values in the datasheet. */ -#define ADXL362_THRESHOLD_RESOLUTION_DECIMAL_MAX 2000 +#define ACCEL_LP_THRESHOLD_RESOLUTION_DECIMAL_MAX 2000 #if IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_12_5) -#define ADXL362_TIMEOUT_MAX_S 5242.88 +#define ACCEL_LP_TIMEOUT_MAX_S 5242.88 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_25) -#define ADXL362_TIMEOUT_MAX_S 2621.44 +#define ACCEL_LP_TIMEOUT_MAX_S 2621.44 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_50) -#define ADXL362_TIMEOUT_MAX_S 1310.72 +#define ACCEL_LP_TIMEOUT_MAX_S 1310.72 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_100) -#define ADXL362_TIMEOUT_MAX_S 655.36 +#define ACCEL_LP_TIMEOUT_MAX_S 655.36 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_200) -#define ADXL362_TIMEOUT_MAX_S 327.68 +#define ACCEL_LP_TIMEOUT_MAX_S 327.68 #elif IS_ENABLED(CONFIG_ADXL362_ACCEL_ODR_400) -#define ADXL362_TIMEOUT_MAX_S 163.84 +#define ACCEL_LP_TIMEOUT_MAX_S 163.84 #endif -#define ADXL362_TIMEOUT_RESOLUTION_MAX 65536 +#define ACCEL_LP_TIMEOUT_RESOLUTION_MAX 65536 /* Local accelerometer threshold value. Used to filter out unwanted values in * the callback from the accelerometer. */ -double threshold = ADXL362_RANGE_MAX_M_S2; +double threshold = ACCEL_LP_RANGE_MAX_M_S2; -struct env_sensor { - enum sensor_channel channel; - const struct device *dev; - struct k_spinlock lock; +/** Sensor struct for the low-power accelerometer */ +static struct env_sensor accel_sensor_lp = { + .channel = SENSOR_CHAN_ACCEL_XYZ, + .dev = DEVICE_DT_GET(DT_ALIAS(accelerometer)), }; +static struct sensor_trigger accel_lp_sensor_trigger_motion = { + .chan = SENSOR_CHAN_ACCEL_XYZ, + .type = SENSOR_TRIG_MOTION +}; + +static struct sensor_trigger accel_lp_sensor_trigger_stationary = { + .chan = SENSOR_CHAN_ACCEL_XYZ, + .type = SENSOR_TRIG_STATIONARY +}; + +#endif /* defined(CONFIG_ADXL362) */ +#if defined(CONFIG_ADXL367) + +/** Sensor struct for the low-power accelerometer */ +static struct env_sensor accel_sensor_lp = { + .channel = SENSOR_CHAN_ACCEL_XYZ, + .dev = DEVICE_DT_GET(DT_ALIAS(accelerometer)), +}; + +static struct sensor_trigger accel_lp_sensor_trigger_motion = { + .chan = SENSOR_CHAN_ACCEL_XYZ, + .type = SENSOR_TRIG_THRESHOLD +}; + +#define ACCEL_LP_THRESHOLD_RESOLUTION_DECIMAL_MAX 8000 +#define ACCEL_LP_TIMEOUT_RESOLUTION_MAX 65535 + +/* 2G range */ +#define ACCEL_LP_RANGE_MAX_M_S2 19.6133 + +/* 400Hz ODR */ +#define ACCEL_LP_TIMEOUT_MAX_S 163.8375 + +double threshold = ACCEL_LP_RANGE_MAX_M_S2; + +#endif /* defined(CONFIG_ADXL367) */ + static struct env_sensor temp_sensor = { .channel = SENSOR_CHAN_AMBIENT_TEMP, .dev = DEVICE_DT_GET(DT_ALIAS(temp_sensor)), @@ -83,22 +127,6 @@ static struct env_sensor iaq_sensor = { }; #endif -/** Sensor struct for the low-power accelerometer */ -static struct env_sensor accel_sensor_lp = { - .channel = SENSOR_CHAN_ACCEL_XYZ, - .dev = DEVICE_DT_GET(DT_ALIAS(accelerometer)), -}; - -static struct sensor_trigger adxl362_sensor_trigger_motion = { - .chan = SENSOR_CHAN_ACCEL_XYZ, - .type = SENSOR_TRIG_MOTION -}; - -static struct sensor_trigger adxl362_sensor_trigger_stationary = { - .chan = SENSOR_CHAN_ACCEL_XYZ, - .type = SENSOR_TRIG_STATIONARY -}; - #if defined(CONFIG_EXTERNAL_SENSORS_IMPACT_DETECTION) static struct sensor_trigger adxl372_sensor_trigger = { .chan = SENSOR_CHAN_ACCEL_XYZ, @@ -123,6 +151,7 @@ static void accelerometer_trigger_handler(const struct device *dev, switch (trig->type) { case SENSOR_TRIG_MOTION: case SENSOR_TRIG_STATIONARY: + case SENSOR_TRIG_THRESHOLD: if (sensor_sample_fetch(dev) < 0) { LOG_ERR("Sample fetch error"); @@ -139,7 +168,7 @@ static void accelerometer_trigger_handler(const struct device *dev, evt.value_array[1] = sensor_value_to_double(&data[1]); evt.value_array[2] = sensor_value_to_double(&data[2]); - if (trig->type == SENSOR_TRIG_MOTION) { + if (trig->type == SENSOR_TRIG_MOTION || trig->type == SENSOR_TRIG_THRESHOLD) { evt.type = EXT_SENSOR_EVT_ACCELEROMETER_ACT_TRIGGER; LOG_DBG("Activity detected"); } else { @@ -230,11 +259,13 @@ int ext_sensors_init(ext_sensor_handler_t handler) evt_handler(&evt); } +#if defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) if (!device_is_ready(accel_sensor_lp.dev)) { LOG_ERR("Low-power accelerometer device is not ready"); evt.type = EXT_SENSOR_EVT_ACCELEROMETER_ERROR; evt_handler(&evt); } +#endif /* defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) */ #if defined(CONFIG_EXTERNAL_SENSORS_IMPACT_DETECTION) if (!device_is_ready(accel_sensor_hg.dev)) { @@ -343,7 +374,7 @@ int ext_sensors_pressure_get(double *ext_press) k_spinlock_key_t key = k_spin_lock(&(press_sensor.lock)); #if defined(CONFIG_BME680) /* Pressure is in kPascals */ - *ext_press = sensor_value_to_double(&data) * 1000.0f; + *ext_press = sensor_value_to_double(&data) * 1000.0; #else /* Pressure is in Pascals */ *ext_press = sensor_value_to_double(&data); @@ -391,8 +422,15 @@ int ext_sensors_air_quality_get(uint16_t *ext_bsec_air_quality) int ext_sensors_accelerometer_threshold_set(double threshold, bool upper) { +#if defined(CONFIG_ADXL367) + if (!upper) { + /* cannot distinguish events on adxl367 yet */ + return 0; + } +#endif /* defined(CONFIG_ADXL367) */ +#if defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) int err, input_value; - double range_max_m_s2 = ADXL362_RANGE_MAX_M_S2; + double range_max_m_s2 = ACCEL_LP_RANGE_MAX_M_S2; struct ext_sensor_evt evt = {0}; if ((threshold > range_max_m_s2) || (threshold <= 0.0)) { @@ -404,14 +442,14 @@ int ext_sensors_accelerometer_threshold_set(double threshold, bool upper) * to the configured measuring range of the accelerometer. */ threshold = (threshold * - (ADXL362_THRESHOLD_RESOLUTION_DECIMAL_MAX / range_max_m_s2)); + (ACCEL_LP_THRESHOLD_RESOLUTION_DECIMAL_MAX / range_max_m_s2)); /* Add 0.5 to ensure proper conversion from double to int. */ threshold = threshold + 0.5; input_value = (int)threshold; - if (input_value >= ADXL362_THRESHOLD_RESOLUTION_DECIMAL_MAX) { - input_value = ADXL362_THRESHOLD_RESOLUTION_DECIMAL_MAX - 1; + if (input_value >= ACCEL_LP_THRESHOLD_RESOLUTION_DECIMAL_MAX) { + input_value = ACCEL_LP_THRESHOLD_RESOLUTION_DECIMAL_MAX - 1; } else if (input_value < 0) { input_value = 0; } @@ -435,22 +473,24 @@ int ext_sensors_accelerometer_threshold_set(double threshold, bool upper) evt_handler(&evt); return err; } +#endif /* defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) */ return 0; } int ext_sensors_inactivity_timeout_set(double inact_time) { +#if defined(CONFIG_ADXL362) int err, inact_time_decimal; struct ext_sensor_evt evt = {0}; - if (inact_time > ADXL362_TIMEOUT_MAX_S || inact_time < 0) { + if (inact_time > ACCEL_LP_TIMEOUT_MAX_S || inact_time < 0) { LOG_ERR("Invalid timeout value"); return -ENOTSUP; } - inact_time = inact_time / ADXL362_TIMEOUT_MAX_S * ADXL362_TIMEOUT_RESOLUTION_MAX; + inact_time = inact_time / ACCEL_LP_TIMEOUT_MAX_S * ACCEL_LP_TIMEOUT_RESOLUTION_MAX; inact_time_decimal = (int) (inact_time + 0.5); - inact_time_decimal = MIN(inact_time_decimal, ADXL362_TIMEOUT_RESOLUTION_MAX); + inact_time_decimal = MIN(inact_time_decimal, ACCEL_LP_TIMEOUT_RESOLUTION_MAX); inact_time_decimal = MAX(inact_time_decimal, 0); const struct sensor_value data = { @@ -468,29 +508,36 @@ int ext_sensors_inactivity_timeout_set(double inact_time) evt_handler(&evt); return err; } +#endif /* defined(CONFIG_ADXL362) */ return 0; } int ext_sensors_accelerometer_trigger_callback_set(bool enable) { - int err; + int err = 0; +#if defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) struct ext_sensor_evt evt = {0}; sensor_trigger_handler_t handler = enable ? accelerometer_trigger_handler : NULL; - err = sensor_trigger_set(accel_sensor_lp.dev, &adxl362_sensor_trigger_motion, handler); +#if defined(CONFIG_ADXL362) + err = sensor_trigger_set(accel_sensor_lp.dev, &accel_lp_sensor_trigger_stationary, handler); if (err) { goto error; } - err = sensor_trigger_set(accel_sensor_lp.dev, &adxl362_sensor_trigger_stationary, handler); +#endif /* defined(CONFIG_ADXL362) */ + + err = sensor_trigger_set(accel_sensor_lp.dev, &accel_lp_sensor_trigger_motion, handler); if (err) { goto error; } - return 0; + return 0; + error: LOG_ERR("Could not set trigger for device %s, error: %d", accel_sensor_lp.dev->name, err); evt.type = EXT_SENSOR_EVT_ACCELEROMETER_ERROR; evt_handler(&evt); +#endif /* defined(CONFIG_ADXL362) || defined(CONFIG_ADXL367) */ return err; } diff --git a/applications/asset_tracker_v2/src/modules/cloud_module.c b/applications/asset_tracker_v2/src/modules/cloud_module.c index 6d5da13e8e7..a24952882a6 100644 --- a/applications/asset_tracker_v2/src/modules/cloud_module.c +++ b/applications/asset_tracker_v2/src/modules/cloud_module.c @@ -855,12 +855,14 @@ static int setup(void) return err; } -#if defined(CONFIG_MCUBOOT_IMG_MANAGER) +#if (defined(CONFIG_MCUBOOT_IMG_MANAGER) && !defined(CONFIG_LWM2M_CARRIER)) /* After a successful initializaton, tell the bootloader that the * current image is confirmed to be working. + * If the LwM2M Carrier library is enabled, allow the library to confirm + * the image. */ boot_write_img_confirmed(); -#endif /* CONFIG_MCUBOOT_IMG_MANAGER */ +#endif /* CONFIG_MCUBOOT_IMG_MANAGER && !CONFIG_LWM2M_CARRIER */ return 0; } diff --git a/applications/asset_tracker_v2/src/modules/data_module.c b/applications/asset_tracker_v2/src/modules/data_module.c index 448b20ae50d..494d5c12d8e 100644 --- a/applications/asset_tracker_v2/src/modules/data_module.c +++ b/applications/asset_tracker_v2/src/modules/data_module.c @@ -1204,12 +1204,18 @@ static void on_all_states(struct data_msg_data *msg) .queued = true }; + new_location_data.pvt.lat = msg->module.location.data.location.pvt.latitude; + new_location_data.pvt.lon = msg->module.location.data.location.pvt.longitude; new_location_data.pvt.acc = msg->module.location.data.location.pvt.accuracy; new_location_data.pvt.alt = msg->module.location.data.location.pvt.altitude; - new_location_data.pvt.hdg = msg->module.location.data.location.pvt.heading; - new_location_data.pvt.lat = msg->module.location.data.location.pvt.latitude; - new_location_data.pvt.longi = msg->module.location.data.location.pvt.longitude; + new_location_data.pvt.alt_acc = + msg->module.location.data.location.pvt.altitude_accuracy; new_location_data.pvt.spd = msg->module.location.data.location.pvt.speed; + new_location_data.pvt.spd_acc = + msg->module.location.data.location.pvt.speed_accuracy; + new_location_data.pvt.hdg = msg->module.location.data.location.pvt.heading; + new_location_data.pvt.hdg_acc = + msg->module.location.data.location.pvt.heading_accuracy; cloud_codec_populate_gnss_buffer(gnss_buf, &new_location_data, &head_gnss_buf, diff --git a/applications/asset_tracker_v2/src/modules/debug_module.c b/applications/asset_tracker_v2/src/modules/debug_module.c index 6640cd55540..7b7836b1424 100644 --- a/applications/asset_tracker_v2/src/modules/debug_module.c +++ b/applications/asset_tracker_v2/src/modules/debug_module.c @@ -264,19 +264,16 @@ static void add_location_metrics(uint8_t satellites, uint32_t search_time, switch (event) { case LOCATION_MODULE_EVT_GNSS_DATA_READY: - err = memfault_metrics_heartbeat_set_unsigned( - MEMFAULT_METRICS_KEY(GnssTimeToFix), - search_time); + err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_time_to_fix_ms, search_time); if (err) { - LOG_ERR("Failed updating GnssTimeToFix metric, error: %d", err); + LOG_ERR("Failed updating gnss_time_to_fix_ms metric, error: %d", err); } break; case LOCATION_MODULE_EVT_TIMEOUT: - err = memfault_metrics_heartbeat_set_unsigned( - MEMFAULT_METRICS_KEY(LocationTimeoutSearchTime), - search_time); + err = MEMFAULT_METRIC_SET_UNSIGNED(location_timeout_search_time_ms, search_time); if (err) { - LOG_ERR("Failed updating LocationTimeoutSearchTime metric, error: %d", err); + LOG_ERR("Failed updating location_timeout_search_time_ms metric, error: %d", + err); } break; default: @@ -284,10 +281,9 @@ static void add_location_metrics(uint8_t satellites, uint32_t search_time, return; } - err = memfault_metrics_heartbeat_set_unsigned(MEMFAULT_METRICS_KEY(GnssSatellitesTracked), - satellites); + err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_satellites_tracked_count, satellites); if (err) { - LOG_ERR("Failed updating GnssSatellitesTracked metric, error: %d", err); + LOG_ERR("Failed updating gnss_satellites_tracked_count metric, error: %d", err); } memfault_metrics_heartbeat_debug_trigger(); diff --git a/applications/asset_tracker_v2/src/modules/location_module.c b/applications/asset_tracker_v2/src/modules/location_module.c index b35f38988bf..b59c094d158 100644 --- a/applications/asset_tracker_v2/src/modules/location_module.c +++ b/applications/asset_tracker_v2/src/modules/location_module.c @@ -217,12 +217,15 @@ static void data_send_pvt(void) { struct location_module_event *location_module_event = new_location_module_event(); - location_module_event->data.location.pvt.longitude = pvt_data.longitude; location_module_event->data.location.pvt.latitude = pvt_data.latitude; - location_module_event->data.location.pvt.altitude = pvt_data.altitude; + location_module_event->data.location.pvt.longitude = pvt_data.longitude; location_module_event->data.location.pvt.accuracy = pvt_data.accuracy; + location_module_event->data.location.pvt.altitude = pvt_data.altitude; + location_module_event->data.location.pvt.altitude_accuracy = pvt_data.altitude_accuracy; location_module_event->data.location.pvt.speed = pvt_data.speed; + location_module_event->data.location.pvt.speed_accuracy = pvt_data.speed_accuracy; location_module_event->data.location.pvt.heading = pvt_data.heading; + location_module_event->data.location.pvt.heading_accuracy = pvt_data.heading_accuracy; location_module_event->data.location.timestamp = k_uptime_get(); location_module_event->type = LOCATION_MODULE_EVT_GNSS_DATA_READY; @@ -395,10 +398,13 @@ void location_event_handler(const struct location_event_data *event_data) LOG_DBG(" method: %s", location_method_str(event_data->method)); LOG_DBG(" latitude: %.06f", event_data->location.latitude); LOG_DBG(" longitude: %.06f", event_data->location.longitude); - LOG_DBG(" accuracy: %.01f m", event_data->location.accuracy); - LOG_DBG(" altitude: %.01f m", event_data->location.details.gnss.pvt_data.altitude); - LOG_DBG(" speed: %.01f m", event_data->location.details.gnss.pvt_data.speed); - LOG_DBG(" heading: %.01f deg", event_data->location.details.gnss.pvt_data.heading); + LOG_DBG(" accuracy: %.01f m", (double)event_data->location.accuracy); + LOG_DBG(" altitude: %.01f m", + (double)event_data->location.details.gnss.pvt_data.altitude); + LOG_DBG(" speed: %.01f m", + (double)event_data->location.details.gnss.pvt_data.speed); + LOG_DBG(" heading: %.01f deg", + (double)event_data->location.details.gnss.pvt_data.heading); if (event_data->location.datetime.valid) { LOG_DBG(" date: %04d-%02d-%02d", @@ -415,8 +421,8 @@ void location_event_handler(const struct location_event_data *event_data) stats.search_time = (uint32_t)(k_uptime_get() - stats.start_uptime); LOG_DBG(" search time: %d ms", stats.search_time); - /* Only GNSS result is handled as cellular is handled - * as part of LOCATION_EVT_CELLULAR_EXT_REQUEST + /* Only GNSS result is handled as cellular and Wi-Fi are handled + * as part of LOCATION_EVT_CLOUD_LOCATION_EXT_REQUEST */ stats.satellites_tracked = 0; if (event_data->method == LOCATION_METHOD_GNSS) { @@ -501,6 +507,17 @@ void location_event_handler(const struct location_event_data *event_data) break; #endif + case LOCATION_EVT_STARTED: + LOG_DBG("Location request has been started with '%s' method", + location_method_str(event_data->method)); + break; + + case LOCATION_EVT_FALLBACK: + LOG_DBG("Location fallback has occurred from '%s' to '%s'", + location_method_str(event_data->method), + location_method_str(event_data->fallback.next_method)); + break; + default: LOG_DBG("Getting location: Unknown event %d", event_data->id); break; diff --git a/applications/asset_tracker_v2/src/modules/modem_module.c b/applications/asset_tracker_v2/src/modules/modem_module.c index 20b30990dd9..8a8e2736db1 100644 --- a/applications/asset_tracker_v2/src/modules/modem_module.c +++ b/applications/asset_tracker_v2/src/modules/modem_module.c @@ -212,7 +212,7 @@ static void lte_evt_handler(const struct lte_lc_evt *const evt) len = snprintf(log_buf, sizeof(log_buf), "eDRX parameter update: eDRX: %.2f, PTW: %.2f", - evt->edrx_cfg.edrx, evt->edrx_cfg.ptw); + (double)evt->edrx_cfg.edrx, (double)evt->edrx_cfg.ptw); if (len > 0) { LOG_DBG("%s", log_buf); } @@ -426,6 +426,12 @@ int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *evt) */ return 1; } + case LWM2M_CARRIER_EVENT_MODEM_DOMAIN: + LOG_INF("LWM2M_CARRIER_EVENT_MODEM_DOMAIN"); + break; + case LWM2M_CARRIER_EVENT_APP_DATA: + LOG_INF("LWM2M_CARRIER_EVENT_APP_DATA"); + break; case LWM2M_CARRIER_EVENT_MODEM_INIT: LOG_INF("LWM2M_CARRIER_EVENT_MODEM_INIT"); err = nrf_modem_lib_init(); diff --git a/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.conf b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.conf new file mode 100644 index 00000000000..7c7ad0095db --- /dev/null +++ b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# MCUboot config to enable secondary slot on the external flash + +CONFIG_FLASH=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_MULTITHREADING=y +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_BOOT_MAX_IMG_SECTORS=256 diff --git a/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.overlay b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.overlay new file mode 100644 index 00000000000..d12f9614a10 --- /dev/null +++ b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/nrf9151dk_nrf9151.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&gd25lb256 { + status = "okay"; +}; + +/ { + /* Configure partition manager to use gd25lb256 as the external flash */ + chosen { + nordic,pm-ext-flash = &gd25lb256; + }; +}; diff --git a/applications/asset_tracker_v2/sysbuild/mcuboot/boards/thingy91x_nrf9151.conf b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/thingy91x_nrf9151.conf new file mode 100644 index 00000000000..ee1a741ca5b --- /dev/null +++ b/applications/asset_tracker_v2/sysbuild/mcuboot/boards/thingy91x_nrf9151.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=512 + +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y diff --git a/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c b/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c index 9030593bfc7..f3afcee4576 100644 --- a/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c +++ b/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c @@ -114,11 +114,9 @@ void test_memfault_trigger_metric_sampling_on_gnss_fix(void) setup_debug_module_in_init_state(); __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(GnssTimeToFix), - 60000, - 0); + MEMFAULT_METRICS_KEY(gnss_time_to_fix_ms), 60000, 0); __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(GnssSatellitesTracked), + MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count), 4, 0); __cmock_memfault_metrics_heartbeat_debug_trigger_Expect(); @@ -144,13 +142,13 @@ void test_memfault_trigger_metric_sampling_on_location_timeout(void) /* Update this function to expect the search time and number of satellites. */ __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(LocationTimeoutSearchTime), - 30000, - 0); + MEMFAULT_METRICS_KEY(location_timeout_search_time_ms), + 30000, + 0); __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(GnssSatellitesTracked), - 2, - 0); + MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count), + 2, + 0); __cmock_memfault_metrics_heartbeat_debug_trigger_Ignore(); __cmock_app_event_manager_alloc_ExpectAnyArgsAndReturn(&location_module_event_memory); diff --git a/applications/asset_tracker_v2/tests/json_common/src/json_validate.h b/applications/asset_tracker_v2/tests/json_common/src/json_validate.h index ebc958ea4a4..e4fc279ed52 100644 --- a/applications/asset_tracker_v2/tests/json_common/src/json_validate.h +++ b/applications/asset_tracker_v2/tests/json_common/src/json_validate.h @@ -16,8 +16,8 @@ "{" \ "\"gnss\":{" \ "\"v\":{" \ - "\"lng\":10," \ "\"lat\":62," \ + "\"lng\":10," \ "\"acc\":24," \ "\"alt\":170," \ "\"spd\":1," \ @@ -179,8 +179,8 @@ "[" \ "{" \ "\"v\":{" \ - "\"lng\":10," \ "\"lat\":62," \ + "\"lng\":10," \ "\"acc\":24," \ "\"alt\":170," \ "\"spd\":1," \ @@ -190,6 +190,20 @@ "}" \ "]" +#define TEST_VALIDATE_ARRAY_GNSS_NO_HEADING_JSON_SCHEMA \ + "[" \ + "{" \ + "\"v\":{" \ + "\"lat\":62," \ + "\"lng\":10," \ + "\"acc\":24," \ + "\"alt\":170," \ + "\"spd\":1" \ + "}," \ + "\"ts\":1563968747123" \ + "}" \ + "]" + #define TEST_VALIDATE_ARRAY_ENVIRONMENTAL_JSON_SCHEMA \ "[" \ "{" \ @@ -302,8 +316,8 @@ "\"gnss\":[" \ "{" \ "\"v\":{" \ - "\"lng\":10," \ "\"lat\":62," \ + "\"lng\":10," \ "\"acc\":24," \ "\"alt\":170," \ "\"spd\":1," \ @@ -313,8 +327,8 @@ "}," \ "{" \ "\"v\":{" \ - "\"lng\":10," \ "\"lat\":62," \ + "\"lng\":10," \ "\"acc\":24," \ "\"alt\":170," \ "\"spd\":1," \ diff --git a/applications/asset_tracker_v2/tests/json_common/src/main.c b/applications/asset_tracker_v2/tests/json_common/src/main.c index 34cff72e96c..01f15674814 100644 --- a/applications/asset_tracker_v2/tests/json_common/src/main.c +++ b/applications/asset_tracker_v2/tests/json_common/src/main.c @@ -158,12 +158,15 @@ void test_encode_gnss_data_object(void) * encoding. */ struct cloud_data_gnss data = { - .pvt.longi = 10, .pvt.lat = 62, + .pvt.lon = 10, .pvt.acc = 24, .pvt.alt = 170, + .pvt.alt_acc = 10, .pvt.spd = 1, + .pvt.spd_acc = 1, .pvt.hdg = 176, + .pvt.hdg_acc = 5, .queued = true, .gnss_ts = 1000 }; @@ -213,12 +216,15 @@ void test_encode_gnss_data_array(void) * encoding. */ struct cloud_data_gnss data = { - .pvt.longi = 10, .pvt.lat = 62, + .pvt.lon = 10, .pvt.acc = 24, .pvt.alt = 170, + .pvt.alt_acc = 10, .pvt.spd = 1, + .pvt.spd_acc = 1, .pvt.hdg = 176, + .pvt.hdg_acc = 5, .queued = true, .gnss_ts = 1000 }; @@ -235,6 +241,38 @@ void test_encode_gnss_data_array(void) TEST_ASSERT_EQUAL(0, ret); } +void test_encode_gnss_data_array_no_heading(void) +{ + int ret; + /* Avoid using high precision floating point values to ease string comparison post + * encoding. + */ + struct cloud_data_gnss data = { + .pvt.lat = 62, + .pvt.lon = 10, + .pvt.acc = 24, + .pvt.alt = 170, + .pvt.alt_acc = 10, + .pvt.spd = 1, + .pvt.spd_acc = 1, + .pvt.hdg = 176, + .pvt.hdg_acc = 180, /* 180 deg heading accuracy means that heading is unknown */ + .queued = true, + .gnss_ts = 1000 + }; + + ret = json_common_gnss_data_add(dummy.array_obj, + &data, + JSON_COMMON_ADD_DATA_TO_ARRAY, + NULL, + NULL); + TEST_ASSERT_EQUAL(0, ret); + + ret = encoded_output_check(dummy.array_obj, TEST_VALIDATE_ARRAY_GNSS_NO_HEADING_JSON_SCHEMA, + data.queued); + TEST_ASSERT_EQUAL(0, ret); +} + /* Environmental */ void test_encode_environmental_data_object(void) @@ -874,21 +912,27 @@ void test_encode_batch_data_object(void) [1].queued = true }; struct cloud_data_gnss gnss[2] = { - [0].pvt.longi = 10, [0].pvt.lat = 62, + [0].pvt.lon = 10, [0].pvt.acc = 24, [0].pvt.alt = 170, + [0].pvt.alt_acc = 10, [0].pvt.spd = 1, + [0].pvt.spd_acc = 1, [0].pvt.hdg = 176, + [0].pvt.hdg_acc = 5, [0].gnss_ts = 1000, [0].queued = true, /* Second entry */ - [1].pvt.longi = 10, [1].pvt.lat = 62, + [1].pvt.lon = 10, [1].pvt.acc = 24, [1].pvt.alt = 170, + [1].pvt.alt_acc = 10, [1].pvt.spd = 1, + [1].pvt.spd_acc = 1, [1].pvt.hdg = 176, + [1].pvt.hdg_acc = 5, [1].gnss_ts = 1000, [1].queued = true }; @@ -1038,12 +1082,15 @@ void test_floating_point_encoding_gnss(void) cJSON *decoded_value_obj; struct cloud_data_gnss decoded_values = {0}; struct cloud_data_gnss data = { - .pvt.longi = 10.417852141870654, .pvt.lat = 63.43278762669529, + .pvt.lon = 10.417852141870654, .pvt.acc = 15.455987930297852, .pvt.alt = 53.67230987548828, + .pvt.alt_acc = 10.12345298374867, .pvt.spd = 0.4443884789943695, + .pvt.spd_acc = 1.12345298374867, .pvt.hdg = 176.12345298374867, + .pvt.hdg_acc = 5.12345298374867, .gnss_ts = 1000, .queued = true }; @@ -1068,29 +1115,29 @@ void test_floating_point_encoding_gnss(void) decoded_value_obj = json_object_decode(decoded_gnss_obj, DATA_VALUE); TEST_ASSERT_NOT_NULL(decoded_value_obj); - cJSON *longitude = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_LONGITUDE); cJSON *latitude = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_LATITUDE); + cJSON *longitude = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_LONGITUDE); cJSON *accuracy = cJSON_GetObjectItem(decoded_value_obj, DATA_MOVEMENT); cJSON *altitude = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_ALTITUDE); cJSON *speed = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_SPEED); cJSON *heading = cJSON_GetObjectItem(decoded_value_obj, DATA_GNSS_HEADING); - TEST_ASSERT_NOT_NULL(longitude); TEST_ASSERT_NOT_NULL(latitude); + TEST_ASSERT_NOT_NULL(longitude); TEST_ASSERT_NOT_NULL(accuracy); TEST_ASSERT_NOT_NULL(altitude); TEST_ASSERT_NOT_NULL(speed); TEST_ASSERT_NOT_NULL(heading); - decoded_values.pvt.longi = longitude->valuedouble; decoded_values.pvt.lat = latitude->valuedouble; + decoded_values.pvt.lon = longitude->valuedouble; decoded_values.pvt.acc = accuracy->valuedouble; decoded_values.pvt.alt = altitude->valuedouble; decoded_values.pvt.spd = speed->valuedouble; decoded_values.pvt.hdg = heading->valuedouble; - TEST_ASSERT_DOUBLE_WITHIN(0.1, data.pvt.longi, decoded_values.pvt.longi); TEST_ASSERT_DOUBLE_WITHIN(0.1, data.pvt.lat, decoded_values.pvt.lat); + TEST_ASSERT_DOUBLE_WITHIN(0.1, data.pvt.lon, decoded_values.pvt.lon); TEST_ASSERT_FLOAT_WITHIN(0.1, data.pvt.acc, decoded_values.pvt.acc); TEST_ASSERT_FLOAT_WITHIN(0.1, data.pvt.alt, decoded_values.pvt.alt); TEST_ASSERT_FLOAT_WITHIN(0.1, data.pvt.spd, decoded_values.pvt.spd); diff --git a/applications/asset_tracker_v2/tests/location_module/CMakeLists.txt b/applications/asset_tracker_v2/tests/location_module/CMakeLists.txt index a18fd68a286..4757b14481b 100644 --- a/applications/asset_tracker_v2/tests/location_module/CMakeLists.txt +++ b/applications/asset_tracker_v2/tests/location_module/CMakeLists.txt @@ -47,6 +47,7 @@ target_compile_options(app PRIVATE -DCONFIG_CLOUD_CODEC_LWM2M_PATH_ENTRY_SIZE_MAX=1 -DCONFIG_LTE_NEIGHBOR_CELLS_MAX=10 -DCONFIG_LOCATION_SERVICE_EXTERNAL=y + -DCONFIG_LOCATION_METHOD_GNSS=y -DCONFIG_LOCATION_METHOD_CELLULAR=y -DCONFIG_NRF_CLOUD_AGNSS=y -DCONFIG_AT_MONITOR_HEAP_SIZE=1024 diff --git a/applications/asset_tracker_v2/tests/lwm2m_codec_helpers/src/lwm2m_codec_helpers_test.c b/applications/asset_tracker_v2/tests/lwm2m_codec_helpers/src/lwm2m_codec_helpers_test.c index 04088da30e2..6bd3351719a 100644 --- a/applications/asset_tracker_v2/tests/lwm2m_codec_helpers/src/lwm2m_codec_helpers_test.c +++ b/applications/asset_tracker_v2/tests/lwm2m_codec_helpers/src/lwm2m_codec_helpers_test.c @@ -111,6 +111,20 @@ void test_codec_helpers_setup_resource_buffers(void) &battery_voltage, sizeof(battery_voltage), sizeof(battery_voltage), LWM2M_RES_DATA_FLAG_RW, 0); + __cmock_lwm2m_set_res_buf_ExpectAndReturn( + &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MODEL_NUMBER_RID), CONFIG_BOARD, + sizeof(CONFIG_BOARD), sizeof(CONFIG_BOARD), LWM2M_RES_DATA_FLAG_RO, 0); + + __cmock_lwm2m_set_res_buf_ExpectAndReturn( + &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, HARDWARE_VERSION_RID), CONFIG_SOC, + sizeof(CONFIG_SOC), sizeof(CONFIG_SOC), LWM2M_RES_DATA_FLAG_RO, 0); + + __cmock_lwm2m_set_res_buf_ExpectAndReturn( + &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MANUFACTURER_RID), + CONFIG_CLOUD_CODEC_MANUFACTURER, sizeof(CONFIG_CLOUD_CODEC_MANUFACTURER), + sizeof(CONFIG_CLOUD_CODEC_MANUFACTURER), LWM2M_RES_DATA_FLAG_RO, 0); + + __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_PRESSURE_ID, 0, TIMESTAMP_RID), &pressure_ts, sizeof(pressure_ts), sizeof(pressure_ts), @@ -128,20 +142,22 @@ void test_codec_helpers_setup_resource_buffers(void) __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_TEMP_SENSOR_ID, 0, SENSOR_UNITS_RID), BME680_TEMP_UNIT, - strlen(BME680_TEMP_UNIT), strlen(BME680_TEMP_UNIT), LWM2M_RES_DATA_FLAG_RO, 0); + strlen(BME680_TEMP_UNIT) + 1, strlen(BME680_TEMP_UNIT) + 1, LWM2M_RES_DATA_FLAG_RO, + 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_HUMIDITY_SENSOR_ID, 0, SENSOR_UNITS_RID), BME680_HUMID_UNIT, - strlen(BME680_HUMID_UNIT), strlen(BME680_HUMID_UNIT), LWM2M_RES_DATA_FLAG_RO, 0); + strlen(BME680_HUMID_UNIT) + 1, strlen(BME680_HUMID_UNIT) + 1, + LWM2M_RES_DATA_FLAG_RO, 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_PRESSURE_ID, 0, SENSOR_UNITS_RID), BME680_PRESSURE_UNIT, - strlen(BME680_PRESSURE_UNIT), strlen(BME680_PRESSURE_UNIT), LWM2M_RES_DATA_FLAG_RO, - 0); + strlen(BME680_PRESSURE_UNIT) + 1, strlen(BME680_PRESSURE_UNIT) + 1, + LWM2M_RES_DATA_FLAG_RO, 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_PUSH_BUTTON_ID, BUTTON1_OBJ_INST_ID, APPLICATION_TYPE_RID), - BUTTON1_APP_NAME, strlen(BUTTON1_APP_NAME), strlen(BUTTON1_APP_NAME), + BUTTON1_APP_NAME, strlen(BUTTON1_APP_NAME) + 1, strlen(BUTTON1_APP_NAME) + 1, LWM2M_RES_DATA_FLAG_RO, 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( @@ -151,7 +167,7 @@ void test_codec_helpers_setup_resource_buffers(void) __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(IPSO_OBJECT_PUSH_BUTTON_ID, BUTTON2_OBJ_INST_ID, APPLICATION_TYPE_RID), - BUTTON2_APP_NAME, strlen(BUTTON2_APP_NAME), strlen(BUTTON2_APP_NAME), + BUTTON2_APP_NAME, strlen(BUTTON2_APP_NAME) + 1, strlen(BUTTON2_APP_NAME) + 1, LWM2M_RES_DATA_FLAG_RO, 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( @@ -454,12 +470,15 @@ void test_codec_helpers_get_configuration_object(void) void test_codec_helpers_set_gnss_data(void) { struct cloud_data_gnss gnss = { - .pvt.longi = 10, .pvt.lat = 62, + .pvt.lon = 10, .pvt.acc = 24, .pvt.alt = 170, + .pvt.alt_acc = 10, .pvt.spd = 1, + .pvt.spd_acc = 1, .pvt.hdg = 176, + .pvt.hdg_acc = 5, .gnss_ts = 1000, .queued = true, }; @@ -474,7 +493,7 @@ void test_codec_helpers_set_gnss_data(void) &LWM2M_OBJ(LWM2M_OBJECT_LOCATION_ID, 0, LATITUDE_RID), gnss.pvt.lat, 0); __cmock_lwm2m_set_f64_ExpectAndReturn( - &LWM2M_OBJ(LWM2M_OBJECT_LOCATION_ID, 0, LONGITUDE_RID), gnss.pvt.longi, 0); + &LWM2M_OBJ(LWM2M_OBJECT_LOCATION_ID, 0, LONGITUDE_RID), gnss.pvt.lon, 0); __cmock_lwm2m_set_f64_ExpectAndReturn( &LWM2M_OBJ(LWM2M_OBJECT_LOCATION_ID, 0, ALTITUDE_RID), alt, 0); @@ -596,30 +615,20 @@ void test_codec_helpers_set_modem_static_data(void) .queued = true, }; - __cmock_lwm2m_set_res_buf_ExpectAndReturn( - &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MODEL_NUMBER_RID), CONFIG_BOARD, - strlen(CONFIG_BOARD), strlen(CONFIG_BOARD), LWM2M_RES_DATA_FLAG_RO, 0); - - __cmock_lwm2m_set_res_buf_ExpectAndReturn( - &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, HARDWARE_VERSION_RID), CONFIG_SOC, - strlen(CONFIG_SOC), strlen(CONFIG_SOC), LWM2M_RES_DATA_FLAG_RO, 0); - - __cmock_lwm2m_set_res_buf_ExpectAndReturn( - &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, MANUFACTURER_RID), - CONFIG_CLOUD_CODEC_MANUFACTURER, strlen(CONFIG_CLOUD_CODEC_MANUFACTURER), - strlen(CONFIG_CLOUD_CODEC_MANUFACTURER), LWM2M_RES_DATA_FLAG_RO, 0); - __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, FIRMWARE_VERSION_RID), modem_static.appv, - strlen(modem_static.appv), strlen(modem_static.appv), LWM2M_RES_DATA_FLAG_RO, 0); + strlen(modem_static.appv) + 1, strlen(modem_static.appv) + 1, + LWM2M_RES_DATA_FLAG_RO, 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, SOFTWARE_VERSION_RID), modem_static.fw, - strlen(modem_static.fw), strlen(modem_static.fw), LWM2M_RES_DATA_FLAG_RO, 0); + strlen(modem_static.fw) + 1, strlen(modem_static.fw) + 1, LWM2M_RES_DATA_FLAG_RO, + 0); __cmock_lwm2m_set_res_buf_ExpectAndReturn( &LWM2M_OBJ(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_SERIAL_NUMBER_ID), modem_static.imei, - strlen(modem_static.imei), strlen(modem_static.imei), LWM2M_RES_DATA_FLAG_RO, 0); + strlen(modem_static.imei) + 1, strlen(modem_static.imei) + 1, + LWM2M_RES_DATA_FLAG_RO, 0); TEST_ASSERT_EQUAL(0, lwm2m_codec_helpers_set_modem_static_data(&modem_static)); } diff --git a/applications/asset_tracker_v2/tests/lwm2m_integration/src/lwm2m_integration_test.c b/applications/asset_tracker_v2/tests/lwm2m_integration/src/lwm2m_integration_test.c index d4d2f37151d..79bb02c0582 100644 --- a/applications/asset_tracker_v2/tests/lwm2m_integration/src/lwm2m_integration_test.c +++ b/applications/asset_tracker_v2/tests/lwm2m_integration/src/lwm2m_integration_test.c @@ -148,6 +148,7 @@ void test_lwm2m_integration_connect(void) uint32_t current_lifetime_expected = 0; uint32_t new_lifetime_expected = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME; + __cmock_lwm2m_utils_connection_manage_Ignore(); __cmock_lwm2m_rd_client_start_AddCallback(&rd_client_set_callback_stub); /* After the uut has been put into state CONNECTED, the lwm2m lifetime resource is @@ -357,12 +358,14 @@ void test_lwm2m_integration_registration_failure(void) void test_lwm2m_integration_registration_update_failure(void) { + __cmock_lwm2m_utils_connection_manage_Ignore(); rd_client_callback(&client, LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT); TEST_ASSERT_EQUAL(CLOUD_WRAP_EVT_CONNECTING, last_cb_type); } void test_lwm2m_integration_registration_update_success(void) { + __cmock_lwm2m_utils_connection_manage_Ignore(); rd_client_callback(&client, LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT); TEST_ASSERT_EQUAL(CLOUD_WRAP_EVT_CONNECTING, last_cb_type); @@ -372,12 +375,14 @@ void test_lwm2m_integration_registration_update_success(void) void test_lwm2m_integration_deregistration_failure(void) { + __cmock_lwm2m_utils_connection_manage_Ignore(); rd_client_callback(&client, LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE); TEST_ASSERT_EQUAL(CLOUD_WRAP_EVT_ERROR, last_cb_type); } void test_lwm2m_integration_network_error(void) { + __cmock_lwm2m_utils_connection_manage_Ignore(); rd_client_callback(&client, LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR); TEST_ASSERT_EQUAL(CLOUD_WRAP_EVT_ERROR, last_cb_type); } diff --git a/applications/asset_tracker_v2/tests/nrf_cloud_codec/src/nrf_cloud_codec_test.c b/applications/asset_tracker_v2/tests/nrf_cloud_codec/src/nrf_cloud_codec_test.c index 17bc249a6ea..cb716a09b90 100644 --- a/applications/asset_tracker_v2/tests/nrf_cloud_codec/src/nrf_cloud_codec_test.c +++ b/applications/asset_tracker_v2/tests/nrf_cloud_codec/src/nrf_cloud_codec_test.c @@ -102,12 +102,39 @@ const static struct cloud_data_gnss gnss_data_example = { .queued = true, .gnss_ts = 1563968747123, .pvt = { - .longi = 30, .lat = 40, + .lon = 30, + .acc = 180, .alt = 245, + .alt_acc = 10, + .spd = 5, + .spd_acc = 1, + .hdg = 39, + .hdg_acc = 5 + } +}; + +#define GNSS_BATCH_EXAMPLE_NO_HEADING \ +"[{"\ + "\"appId\":\"GNSS\","\ + "\"messageType\":\"DATA\","\ + "\"ts\":1563968747123,"\ + "\"data\":{\"lng\":30,\"lat\":40,\"acc\":180,\"alt\":245,\"spd\":5}"\ +"}]" + +const static struct cloud_data_gnss gnss_data_example_no_heading = { + .queued = true, + .gnss_ts = 1563968747123, + .pvt = { + .lat = 40, + .lon = 30, .acc = 180, + .alt = 245, + .alt_acc = 10, .spd = 5, - .hdg = 39 + .spd_acc = 1, + .hdg = 39, + .hdg_acc = 180 } }; @@ -521,6 +548,31 @@ void test_enc_batch_data_gnss(void) TEST_ASSERT_FALSE(gnss_buf.queued); } +/* tests batch encoding GNSS data without heading */ +void test_enc_batch_data_gnss_no_heading(void) +{ + struct cloud_data_gnss gnss_buf = gnss_data_example_no_heading; + struct cloud_data_sensors sensor_buf = {0}; + struct cloud_data_modem_static modem_stat_buf = {0}; + struct cloud_data_modem_dynamic modem_dyn_buf = {0}; + struct cloud_data_ui ui_buf = {0}; + struct cloud_data_impact impact_buf = {0}; + struct cloud_data_battery bat_buf = {0}; + + ret = cloud_codec_encode_batch_data(&codec, + &gnss_buf, + &sensor_buf, + &modem_stat_buf, + &modem_dyn_buf, + &ui_buf, + &impact_buf, + &bat_buf, + 1, 1, 1, 1, 1, 1, 1); + TEST_ASSERT_EQUAL(EXIT_SUCCESS, ret); + TEST_ASSERT_EQUAL_STRING(GNSS_BATCH_EXAMPLE_NO_HEADING, codec.buf); + TEST_ASSERT_FALSE(gnss_buf.queued); +} + /* tests batch encoding typical dynamic modem data */ void test_enc_batch_data_modem_dynamic(void) { diff --git a/applications/asset_tracker_v2/tests/ui_module/testcase.yaml b/applications/asset_tracker_v2/tests/ui_module/testcase.yaml index 882916082d1..ae09e99cf6c 100644 --- a/applications/asset_tracker_v2/tests/ui_module/testcase.yaml +++ b/applications/asset_tracker_v2/tests/ui_module/testcase.yaml @@ -1,8 +1,7 @@ tests: asset_tracker_v2.ui_module_test.tester: - platform_allow: native_sim qemu_cortex_m3 nrf9160dk_nrf9160_ns + platform_allow: native_sim nrf9160dk_nrf9160_ns integration_platforms: - native_sim - - qemu_cortex_m3 - nrf9160dk_nrf9160_ns tags: ui_module diff --git a/applications/connectivity_bridge/CMakeLists.txt b/applications/connectivity_bridge/CMakeLists.txt index 30eb85c276c..8d8b4ac9484 100644 --- a/applications/connectivity_bridge/CMakeLists.txt +++ b/applications/connectivity_bridge/CMakeLists.txt @@ -7,15 +7,40 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +find_package(Git) project(NONE) # NORDIC SDK APP START target_sources(app PRIVATE src/main.c) # NORDIC SDK APP END +# Generate a C header file with the readme text as a string variable +set(OUTPUT_README_HEADER_FILE "${CMAKE_BINARY_DIR}/generated/readme/readme.h") +set(INPUT_README_FILE ${CMAKE_SOURCE_DIR}/boards/${BOARD}_readme.txt) +if(NOT EXISTS ${INPUT_README_FILE}) +message(WARNING "${INPUT_README_FILE} does not exist") +set(INPUT_README_FILE ${CMAKE_SOURCE_DIR}/README_TEMPLATE.txt) +endif() +file(READ ${INPUT_README_FILE} README_CONTENT) +if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") + string(APPEND README_CONTENT "\nFirmware version: ${GIT_HASH} Build date: ${CURRENT_DATE}") +endif() +string(REPLACE "\"" "\\\"" README_CONTENT "${README_CONTENT}") +string(REPLACE "\n" "\\n\"\n\"" README_CONTENT "${README_CONTENT}") +file(WRITE ${OUTPUT_README_HEADER_FILE} "\"${README_CONTENT}\"") + + # Include application events and disk files zephyr_library_include_directories( src/events + ${CMAKE_BINARY_DIR}/generated/readme ) # Application sources diff --git a/applications/connectivity_bridge/README_TEMPLATE.txt b/applications/connectivity_bridge/README_TEMPLATE.txt new file mode 100644 index 00000000000..961805b1bb6 --- /dev/null +++ b/applications/connectivity_bridge/README_TEMPLATE.txt @@ -0,0 +1,11 @@ +============================== + Nordic Connectivity Bridge +============================= + +This device is running Nordic's Connectivity bridge application. + +Depending on configuration, the Connectivity bridge can offer the following functions: +* UART-USB bridge for two UART ports +* UART-BLE bridge for the first port using Nordic UART Service + +Create a board-specific README file before deploying your firmware. diff --git a/applications/connectivity_bridge/boards/thingy91_nrf52840.conf b/applications/connectivity_bridge/boards/thingy91_nrf52840.conf new file mode 100644 index 00000000000..2407c48f6fb --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91_nrf52840.conf @@ -0,0 +1,27 @@ +CONFIG_BT=y +CONFIG_BT_DEVICE_NAME="Thingy:91 UART" +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6 +CONFIG_BT_PERIPHERAL_PREF_MAX_INT=16 +CONFIG_BT_PERIPHERAL_PREF_LATENCY=0 +CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=400 +CONFIG_BT_BONDABLE=n +CONFIG_BT_LL_SOFTDEVICE=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_AUTO_PHY_UPDATE=y +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_HCI_ACL_FLOW_CONTROL=y +CONFIG_BT_L2CAP_TX_MTU=247 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_NUS=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_SMP=y +CONFIG_BT_CTLR=y +CONFIG_BT_CTLR_RX_BUFFERS=10 +CONFIG_BT_BUF_ACL_TX_COUNT=10 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 + +CONFIG_USB_MAX_POWER=250 +CONFIG_USB_DEVICE_PRODUCT="Thingy:91 UART" diff --git a/applications/connectivity_bridge/boards/thingy91_nrf52840.overlay b/applications/connectivity_bridge/boards/thingy91_nrf52840.overlay new file mode 100644 index 00000000000..ab9fbd46694 --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91_nrf52840.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + clk-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + dio-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + noe-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + port-write-cycles = <2>; + }; + + rtt0: rtt_chan0 { + compatible = "segger,rtt-uart"; + status = "okay"; + }; + + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <128>; + }; + chosen { + zephyr,console = &rtt0; + zephyr,shell-uart = &rtt0; + zephyr,uart-mcumgr = &rtt0; + zephyr,bt-mon-uart = &rtt0; + zephyr,bt-c2h-uart = &rtt0; + }; +}; + +&uart1 { + status = "okay"; +}; + +&zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + + cdc_acm_uart1: cdc_acm_uart1 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; diff --git a/applications/connectivity_bridge/boards/thingy91_nrf52840_readme.txt b/applications/connectivity_bridge/boards/thingy91_nrf52840_readme.txt new file mode 100644 index 00000000000..d2c11ca05be --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91_nrf52840_readme.txt @@ -0,0 +1,27 @@ +==================== + Nordic Thingy:91 +==================== + +Full Nordic Thingy:91 documentation can be found here: +https://nordicsemi.com/thingy91 + +This USB interface has the following functions: +* Disk drive containing this file and others +* COM ports for nRF91 debug, trace, and firmware update + +COM Ports +==================== + +This USB interface exposes two COM ports mapped to the physical UART interfaces between the nRF91 Series and nRF52840 devices. +When opening these ports manually (without using the LTE Link Monitor), be aware that the USB COM port baud rate selection is applied to the UART. + +Bluetooth® LE Central UART Service +================================== + +This device advertises as "Thingy:91 UART". +Connect using a Bluetooth LE Central device, for example a phone running the nRF Connect app: +https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile/ + +NOTE: The Bluetooth LE interface is unencrypted and intended to be used during debugging. + By default, the Bluetooth LE interface is disabled. + Enable it by setting the appropriate option in Config.txt. diff --git a/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.conf b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..2105087bdc1 --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.conf @@ -0,0 +1,25 @@ +CONFIG_BT=y +CONFIG_BT_DEVICE_NAME="Thingy:91 X UART" +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6 +CONFIG_BT_PERIPHERAL_PREF_MAX_INT=16 +CONFIG_BT_PERIPHERAL_PREF_LATENCY=0 +CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=400 +CONFIG_BT_BONDABLE=n + +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_AUTO_PHY_UPDATE=y +CONFIG_BT_DATA_LEN_UPDATE=y +CONFIG_BT_HCI_ACL_FLOW_CONTROL=y +CONFIG_BT_L2CAP_TX_MTU=247 +CONFIG_BT_BUF_ACL_RX_SIZE=251 +CONFIG_BT_NUS=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_SMP=y +CONFIG_BT_BUF_ACL_TX_COUNT=10 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 + +CONFIG_USB_MAX_POWER=250 +CONFIG_USB_DEVICE_PRODUCT="Thingy:91 X UART" diff --git a/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.overlay b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..a21add6fa13 --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + clk-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + dio-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + noe-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + port-write-cycles = <2>; + }; + + chosen { + zephyr,console = &rtt0; + zephyr,shell-uart = &rtt0; + zephyr,uart-mcumgr = &rtt0; + zephyr,bt-mon-uart = &rtt0; + zephyr,bt-c2h-uart = &rtt0; + }; + + ramdisk0 { + compatible = "zephyr,ram-disk"; + disk-name = "RAM"; + sector-size = <512>; + sector-count = <128>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + + +&zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + + cdc_acm_uart1: cdc_acm_uart1 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; diff --git a/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp_readme.txt b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp_readme.txt new file mode 100644 index 00000000000..f4d5cd27132 --- /dev/null +++ b/applications/connectivity_bridge/boards/thingy91x_nrf5340_cpuapp_readme.txt @@ -0,0 +1,26 @@ +===================== + Nordic Thingy:91 X +===================== + +This USB interface has the following functions: +* Disk drive containing this file and others +* COM ports for nRF91 debug, trace, and firmware update + +COM Ports +==================== +This USB interface exposes two COM ports mapped to the physical UART interfaces between the nRF91 and nRF5340 devices. +When opening these ports manually (without using LTE Link Monitor) be aware that the USB COM port baud rate selection is applied to the UART. + +This USB interface exposes two COM ports mapped to the physical UART interfaces between the nRF91 Series and nRF5340 devices. +When opening these ports manually (without using the LTE Link Monitor), be aware that the USB COM port baud rate selection is applied to the UART. + +Bluetooth® LE Central UART Service +================================== + +This device advertises as "Thingy:91 X UART". +Connect using a Bluetooth LE Central device, for example a phone running the nRF Connect app: +https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile/ + +NOTE: The Bluetooth LE interface is unencrypted and intended to be used during debugging. + By default, the Bluetooth LE interface is disabled. + Enable it by setting the appropriate option in Config.txt. diff --git a/applications/connectivity_bridge/prj.conf b/applications/connectivity_bridge/prj.conf index 806372a63e9..a17b6081e50 100644 --- a/applications/connectivity_bridge/prj.conf +++ b/applications/connectivity_bridge/prj.conf @@ -19,7 +19,6 @@ CONFIG_BRIDGE_BLE_ENABLE=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_REMOTE_WAKEUP=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" -CONFIG_USB_DEVICE_PRODUCT="Thingy:91 UART" CONFIG_USB_DEVICE_VID=0x1915 CONFIG_USB_DEVICE_PID=0x9100 CONFIG_USB_DEVICE_SN="THINGY91 12PLACEHLDRS" # This is overridden at runtime @@ -71,33 +70,11 @@ CONFIG_UART_0_NRF_HW_ASYNC=y CONFIG_UART_1_NRF_HW_ASYNC=y CONFIG_UART_0_NRF_HW_ASYNC_TIMER=1 CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_NRFX_UARTE0=y CONFIG_NRFX_UARTE1=y CONFIG_NRFX_TIMER1=y CONFIG_NRFX_TIMER2=y CONFIG_NRFX_PPI=y -# BLE -CONFIG_BT=y -CONFIG_BT_DEVICE_NAME="Thingy:91 UART" -CONFIG_BT_DEVICE_NAME_DYNAMIC=y -CONFIG_BT_PERIPHERAL=y -CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6 -CONFIG_BT_PERIPHERAL_PREF_MAX_INT=16 -CONFIG_BT_PERIPHERAL_PREF_LATENCY=0 -CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=400 -CONFIG_BT_BONDABLE=n -CONFIG_BT_LL_SOFTDEVICE=y -CONFIG_BT_MAX_CONN=1 -CONFIG_BT_AUTO_PHY_UPDATE=y -CONFIG_BT_DATA_LEN_UPDATE=y -CONFIG_BT_HCI_ACL_FLOW_CONTROL=y -CONFIG_BT_L2CAP_TX_MTU=247 -CONFIG_BT_BUF_ACL_RX_SIZE=251 -CONFIG_BT_NUS=y -CONFIG_BT_GATT_CLIENT=y -CONFIG_BT_SMP=y -CONFIG_BT_CTLR=y -CONFIG_BT_BUF_ACL_TX_COUNT=10 -CONFIG_BT_BUF_ACL_TX_SIZE=251 -CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_HW_ID_LIBRARY=y diff --git a/applications/connectivity_bridge/sample.yaml b/applications/connectivity_bridge/sample.yaml index ffa916dade3..20cac2d5f19 100644 --- a/applications/connectivity_bridge/sample.yaml +++ b/applications/connectivity_bridge/sample.yaml @@ -4,7 +4,9 @@ sample: tests: applications.connectivity_bridge: build_only: true - platform_allow: thingy91_nrf52840 + platform_allow: + - thingy91_nrf52840 + - thingy91x_nrf5340_cpuapp integration_platforms: - thingy91_nrf52840 tags: ci_build diff --git a/applications/connectivity_bridge/src/disk/config.c b/applications/connectivity_bridge/src/disk/config.c index 4cd6d8a1237..dffb1fbb2f5 100644 --- a/applications/connectivity_bridge/src/disk/config.c +++ b/applications/connectivity_bridge/src/disk/config.c @@ -110,8 +110,8 @@ static struct cfg_option configs[] = { }; static const char file_contents_header[] = -"==========================================\r\n" -" Nordic Thingy:91 Configuration options\r\n" +"=========================\r\n" +" Configuration options\r\n" "==========================================\r\n" "The parameters below can be changed at runtime.\r\n" "\r\n" diff --git a/applications/connectivity_bridge/src/disk/readme.c b/applications/connectivity_bridge/src/disk/readme.c index b68c1198127..cfa5c6ffbd9 100644 --- a/applications/connectivity_bridge/src/disk/readme.c +++ b/applications/connectivity_bridge/src/disk/readme.c @@ -9,6 +9,10 @@ #define MODULE file_readme #include "fs_event.h" +static const char file_contents[] = { +#include "readme.h" +}; + #if CONFIG_FS_FATFS_LFN #define FILE_NAME "README.txt" #else @@ -17,45 +21,6 @@ #define FILE_CONTENTS file_contents #define FILE_CONTENTS_LEN strlen(file_contents) -static const char file_contents[] = - "====================\r\n" - " Nordic Thingy:91 \r\n" - "====================\r\n" - "\r\n" - "Full Nordic Thingy:91 documentation can be found here:\r\n" - "https://infocenter.nordicsemi.com/topic/ug_thingy91/UG/thingy91/intro/frontpage.html?cp=12_0\r\n" - "\r\n" - "This USB interface has the following functions:\r\n" - "- Disk drive containing this file and others\r\n" -#if CONFIG_BRIDGE_CDC_ENABLE - "- COM ports for nRF91 debug, trace, and firmware update\r\n" -#endif - "\r\n" - "For LTE link and debug monitoring, please see:\r\n" - "https://infocenter.nordicsemi.com/topic/ug_thingy91/UG/thingy91/getting_started/connecting_lte_link_monitor.html?cp=12_0_2_0\r\n" - -#if CONFIG_BRIDGE_CDC_ENABLE - "\r\n" - "COM Ports\r\n" - "====================\r\n" - "This USB interface exposes two COM ports mapped to the physical UART interfaces between the nRF91 and nRF52840 SoCs.\r\n" - "When opening these ports manually (without using LTE Link Monitor) be aware that the USB COM port baud rate selection is applied to the UART.\r\n" -#endif - -#if CONFIG_BRIDGE_BLE_ENABLE - "\r\n" - "BLE UART Service\r\n" - "====================\r\n" - "This device will advertise as \"" CONFIG_BT_DEVICE_NAME "\".\r\n" - "Connect using a BLE Central device, for example a phone running the nRF Connect app:\r\n" - "https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile/\r\n" - "\r\n" - "NOTE: The BLE interface is unencrypted and intended to be used during debugging.\r\n" - " By default the BLE interface is disabled.\r\n" - " Enable it by setting the appropriate option in Config.txt.\r\n" -#endif -; - static bool app_event_handler(const struct app_event_header *aeh) { if (is_fs_event(aeh)) { diff --git a/applications/connectivity_bridge/src/main.c b/applications/connectivity_bridge/src/main.c index 81d57d67d5b..dbdaed4b637 100644 --- a/applications/connectivity_bridge/src/main.c +++ b/applications/connectivity_bridge/src/main.c @@ -7,6 +7,7 @@ #include #include +#include #define MODULE main #include "module_state_event.h" @@ -14,17 +15,22 @@ #include LOG_MODULE_REGISTER(MODULE); -#define USB_SERIALNUMBER_TEMPLATE "THINGY91_%04X%08X" - static uint8_t usb_serial_str[] = "THINGY91_12PLACEHLDRS"; /* Overriding weak function to set iSerialNumber at runtime. */ uint8_t *usb_update_sn_string_descriptor(void) { - snprintk(usb_serial_str, sizeof(usb_serial_str), USB_SERIALNUMBER_TEMPLATE, +#if defined(CONFIG_SOC_SERIES_NRF52X) + snprintk(usb_serial_str, sizeof(usb_serial_str), "THINGY91_%04X%08X", (uint32_t)(NRF_FICR->DEVICEADDR[1] & 0x0000FFFF)|0x0000C000, (uint32_t)NRF_FICR->DEVICEADDR[0]); +#else + char buf[HW_ID_LEN] = {0}; + if (!hw_id_get(buf, ARRAY_SIZE(buf))) { + snprintk(usb_serial_str, sizeof(usb_serial_str), "THINGY91_%s", buf); + } +#endif return usb_serial_str; } diff --git a/applications/connectivity_bridge/src/modules/power_handler.c b/applications/connectivity_bridge/src/modules/power_handler.c index 3ec3a2f8f5b..06996418f53 100644 --- a/applications/connectivity_bridge/src/modules/power_handler.c +++ b/applications/connectivity_bridge/src/modules/power_handler.c @@ -56,7 +56,9 @@ static bool app_event_handler(const struct app_event_header *aeh) } if (is_power_down_event(aeh)) { +#if defined(CONFIG_SOC_SERIES_NRF52X) nrf_power_system_off(NRF_POWER); +#endif } /* If event is unhandled, unsubscribe. */ diff --git a/applications/ipc_radio/CMakeLists.txt b/applications/ipc_radio/CMakeLists.txt new file mode 100644 index 00000000000..dfcc9c186ae --- /dev/null +++ b/applications/ipc_radio/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(ipc_radio) + +target_include_directories(app PRIVATE ./src) + +target_sources_ifdef(CONFIG_IPC_RADIO_802154 app PRIVATE src/802154.c) + +if(CONFIG_IPC_RADIO_BT_HCI_IPC) + target_sources(app PRIVATE src/bt_hci_ipc.c) +else() + target_sources(app PRIVATE src/bt_empty.c) +endif() + +# NORDIC SDK APP START +target_sources(app PRIVATE + src/main.c +) +# NORDIC SDK APP END diff --git a/applications/ipc_radio/Kconfig b/applications/ipc_radio/Kconfig new file mode 100644 index 00000000000..82550a967d9 --- /dev/null +++ b/applications/ipc_radio/Kconfig @@ -0,0 +1,53 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +mainmenu "Nordic ipc_radio firmware" + +config IPC_RADIO_802154 + bool "IPC IEEE 802.15.4 radio" + select NRF_802154_SER_RADIO + help + Enable the IPC IEEE 802.15.4 radio serialization. + +config IPC_RADIO_BT + bool "IPC Bluetooth" + help + Enable the IPC Bluetooth radio serialization. + +if IPC_RADIO_BT + +choice IPC_RADIO_BT_SER + default IPC_RADIO_BT_HCI_IPC + prompt "Bluetooth serialization type" + help + Type of the IPC Bluetooth radio serialization used. + +config IPC_RADIO_BT_HCI_IPC + bool "Bluetooth HCI serialization" + depends on IPC_SERVICE + depends on BT_HCI_RAW + help + Use Bluetooth HCI serialization over ipc_service. + +config IPC_RADIO_BT_RPC + bool "Bluetooth host API serialization over RPC" + depends on BT_RPC_HOST + help + Use nRF RPC serialization for Bluetooth. + +endchoice # IPC_RADIO_BT_SER + +config BT_MAX_CONN + default 4 if IPC_RADIO_802154 + default 16 if !IPC_RADIO_802154 + +endif # IPC_RADIO_BT + +module = IPC_RADIO +module-str = "ipc_radio" +source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" + +source "Kconfig.zephyr" diff --git a/applications/ipc_radio/README.rst b/applications/ipc_radio/README.rst new file mode 100644 index 00000000000..039d62a9038 --- /dev/null +++ b/applications/ipc_radio/README.rst @@ -0,0 +1,127 @@ +.. _ipc_radio: + +IPC radio firmware +################## + +.. contents:: + :local: + :depth: 2 + +The IPC radio firmware allows to use the radio peripheral from another core in a multicore device. + +Application overview +******************** + +You can use this firmware as a general serialized radio peripheral. + +The firmware supports both Bluetooth® Low Energy and IEEE 802.15.4 simultaneously. +In addition, you can configure the Bluetooth selection as an HCI :ref:`bluetooth_controller` or an RPC serialization interface (:ref:`ble_rpc`). + +HCI IPC serialization +===================== + +The firmware exposes the :ref:`bluetooth_controller` support to another core using the IPC subsystem. + +Host for nRF RPC Bluetooth Low Energy +===================================== + +The firmware is running the full Bluetooth Low Energy stack. +It receives serialized function calls that it decodes and executes, then sends response data to the client. + +The serialization includes: + +* :ref:`bt_gap` +* :ref:`bluetooth_connection_mgmt` +* :ref:`bt_gatt` +* :ref:`Bluetooth Cryptography ` + +IEEE 802.15.4 +============= + +The firmware exposes radio driver support to another core using the IPC subsystem. + +Requirements +************ + +The firmware supports the following development kits: + +.. table-from-sample-yaml:: + +To automatically attach the firmware image, you need to use Zephyr's :ref:`zephyr:sysbuild`. + +The |nRFVSC| supports sysbuild during `build configuration setup `_. +To learn more about sysbuild in the extension, see `sysbuild support`_ page in its documentation. + +Configuration +************* + +|config| + +Application +=========== + +You can set the supported radio configurations using the following Kconfig options: + +* :kconfig:option:`CONFIG_IPC_RADIO_BT` - For the Bluetooth Low Energy serialization. +* :kconfig:option:`CONFIG_IPC_RADIO_802154` - For the IEEE 802.15.4 serialization. + +You can select the Bluetooth Low Energy serialization using the :kconfig:option:`CONFIG_IPC_RADIO_BT_SER` Kconfig option. + +The Bluetooth Low Energy and IEEE 802.15.4 functionalities can operate simultaneously and are only limited by available memory. + +Sysbuild +======== + +To enable the firmware, use the Sysbuild configuration of :kconfig:option:`SB_CONFIG_NRF_DEFAULT_IPC_RADIO`. + +You can set the supported radio configurations using the following (Sysbuild) Kconfig options: + +* :kconfig:option:`SB_CONFIG_NETCORE_IPC_RADIO_BT_HCI_IPC` +* :kconfig:option:`SB_CONFIG_NETCORE_IPC_RADIO_BT_RPC` +* :kconfig:option:`SB_CONFIG_NETCORE_IPC_RADIO_IEEE802154` + +Configuration files +=================== + +The application provides predefined configuration files for typical use cases. +You can find the configuration files in the application directory. + +The following files are available: + +* :file:`overlay-802154.conf` - Configuration file enabling IEEE 802.15.4. +* :file:`overlay-bt_hci_ipc.conf` - Configuration file enabling Bluetooth Low Energy over HCI. +* :file:`overlay-bt_rpc.conf` - Configuration file enabling Bluetooth Low Energy over RPC. + +.. note:: + When you use sysbuild to build an application which uses the ipc_radio as network core image the preceding configuration files are added automatically to ipc_radio. + The selection of specific configuration files is determined by the sysbuild kconfig. + + For instance the :kconfig:option:`SB_CONFIG_NETCORE_IPC_RADIO_IEEE802154` kconfig enables the :file:`overlay-802154.conf` configuration file to be used with ipc_radio. + +Building and running as a single image +************************************** + +.. |application path| replace:: :file:`applications/ipc_radio` + +.. include:: /includes/application_build_and_run.txt + +For instructions on how to enable a specific configuration overlay file, see :ref:`building_advanced`. + +.. note:: + You cannot use :ref:`ble_rpc` together with the HCI :ref:`bluetooth_controller`. + +Dependencies +************ + +The dependencies may vary according to the configuration. + +This firmware can use the following |NCS| libraries: + +* :ref:`softdevice_controller` +* :ref:`nrf_802154_sl` +* :ref:`mpsl` +* :ref:`ble_rpc` + +It can use the following `sdk-nrfxlib`_ library: + +* :ref:`nrfxlib:nrf_rpc` diff --git a/applications/ipc_radio/overlay-802154.conf b/applications/ipc_radio/overlay-802154.conf new file mode 100644 index 00000000000..cdb702838b4 --- /dev/null +++ b/applications/ipc_radio/overlay-802154.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +CONFIG_IPC_RADIO_802154=y diff --git a/applications/ipc_radio/overlay-bt_hci_ipc.conf b/applications/ipc_radio/overlay-bt_hci_ipc.conf new file mode 100644 index 00000000000..f08b7f62183 --- /dev/null +++ b/applications/ipc_radio/overlay-bt_hci_ipc.conf @@ -0,0 +1,24 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_RAW_RESERVE=1 + +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y + +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/applications/ipc_radio/overlay-bt_rpc.conf b/applications/ipc_radio/overlay-bt_rpc.conf new file mode 100644 index 00000000000..fcd0273fbe6 --- /dev/null +++ b/applications/ipc_radio/overlay-bt_rpc.conf @@ -0,0 +1,32 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_NRF_RPC_THREAD_STACK_SIZE=4096 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 + +CONFIG_BT=y +CONFIG_BT_RPC=y +CONFIG_BT_RPC_HOST=y + +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_MAX_PAIRED=1 +CONFIG_BT_SMP=y + +# Host side registers all GATT services using dynamic database +CONFIG_BT_GATT_DYNAMIC_DB=y + +# Enable bonding +CONFIG_BT_SETTINGS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS=y + +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_RPC=y diff --git a/applications/ipc_radio/prj.conf b/applications/ipc_radio/prj.conf new file mode 100644 index 00000000000..77b0c3e69f2 --- /dev/null +++ b/applications/ipc_radio/prj.conf @@ -0,0 +1,9 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n diff --git a/applications/ipc_radio/sample.yaml b/applications/ipc_radio/sample.yaml new file mode 100644 index 00000000000..3c83abe14b8 --- /dev/null +++ b/applications/ipc_radio/sample.yaml @@ -0,0 +1,36 @@ +sample: + name: IPC radio firmware + description: IPC radio firmware application +tests: + applications.ipc_radio.hci: + build_only: true + platform_allow: nrf5340dk_nrf5340_cpunet thingy53_nrf5340_cpunet + tags: bluetooth ci_build + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - thingy53_nrf5340_cpunet + extra_args: EXTRA_CONF_FILE=overlay-bt_hci_ipc.conf + applications.ipc_radio.rpc: + build_only: true + platform_allow: nrf5340dk_nrf5340_cpunet thingy53_nrf5340_cpunet + tags: bluetooth ci_build + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - thingy53_nrf5340_cpunet + extra_args: EXTRA_CONF_FILE=overlay-bt_rpc.conf + applications.ipc_radio.802154: + build_only: true + platform_allow: nrf5340dk_nrf5340_cpunet thingy53_nrf5340_cpunet + tags: ci_build + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - thingy53_nrf5340_cpunet + extra_args: EXTRA_CONF_FILE=overlay-802154.conf + applications.ipc_radio.hci802154: + build_only: true + platform_allow: nrf5340dk_nrf5340_cpunet thingy53_nrf5340_cpunet + tags: bluetooth ci_build + integration_platforms: + - nrf5340dk_nrf5340_cpunet + - thingy53_nrf5340_cpunet + extra_args: EXTRA_CONF_FILE="overlay-bt_hci_ipc.conf;overlay-802154.conf" diff --git a/applications/ipc_radio/src/802154.c b/applications/ipc_radio/src/802154.c new file mode 100644 index 00000000000..32077119969 --- /dev/null +++ b/applications/ipc_radio/src/802154.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +void nrf_802154_serialization_error(const nrf_802154_ser_err_data_t *err) +{ + ARG_UNUSED(err); + __ASSERT(false, "802.15.4 serialization error"); + k_oops(); +} + +void nrf_802154_sl_fault_handler(uint32_t id, int32_t line, const char *err) +{ + __ASSERT(false, "module_id: %u, line: %d, %s", id, line, err); + k_oops(); +} diff --git a/applications/ipc_radio/src/bt_empty.c b/applications/ipc_radio/src/bt_empty.c new file mode 100644 index 00000000000..e12a8f27720 --- /dev/null +++ b/applications/ipc_radio/src/bt_empty.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +#include "ipc_bt.h" + +LOG_MODULE_DECLARE(ipc_radio, CONFIG_IPC_RADIO_LOG_LEVEL); + +int ipc_bt_init(void) +{ + LOG_DBG("Empty ipc_bt_init called."); + return -ENOSYS; +} + +int ipc_bt_process(void) +{ + LOG_DBG("Empty ipc_bt_process called."); + return -ENOSYS; +} diff --git a/applications/ipc_radio/src/bt_hci_ipc.c b/applications/ipc_radio/src/bt_hci_ipc.c new file mode 100644 index 00000000000..161cdeef985 --- /dev/null +++ b/applications/ipc_radio/src/bt_hci_ipc.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) +#include +#endif /* CONFIG_BT_HCI_VS_FATAL_ERROR */ + +#include + +#include "ipc_bt.h" + +LOG_MODULE_DECLARE(ipc_radio, CONFIG_IPC_RADIO_LOG_LEVEL); + +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) || defined(CONFIG_BT_HCI_VS_FATAL_ERROR) +static bool ipc_ept_ready; +#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER || CONFIG_BT_HCI_VS_FATAL_ERROR */ + +static K_SEM_DEFINE(ipc_bound_sem, 0, 1); + +static struct ipc_ept hci_ept; + +static K_FIFO_DEFINE(tx_queue); +static K_FIFO_DEFINE(rx_queue); + +enum hci_h4_type { + HCI_H4_CMD = 0x01, /* rx */ + HCI_H4_ACL = 0x02, /* rx */ + HCI_H4_EVT = 0x04, /* tx */ + HCI_H4_ISO = 0x05 /* rx */ +}; + +#define HCI_FATAL_MSG true +#define HCI_REGULAR_MSG false + +static void recv_cmd(const uint8_t *data, size_t len) +{ + const struct bt_hci_cmd_hdr *hdr = (const struct bt_hci_cmd_hdr *)data; + struct net_buf *buf; + + if (len < sizeof(*hdr)) { + LOG_ERR("Not enough data for command header."); + return; + } + + if ((len - sizeof(*hdr)) != hdr->param_len) { + LOG_ERR("Command param_len does not match the remaining data length."); + return; + } + + buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, hdr, sizeof(*hdr)); + if (!buf) { + LOG_ERR("No available command buffers."); + return; + } + + data += sizeof(*hdr); + len -= sizeof(*hdr); + + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer."); + net_buf_unref(buf); + return; + } + + LOG_DBG("Received HCI CMD packet (opcode: %#x, len: %u).", + sys_le16_to_cpu(hdr->opcode), hdr->param_len); + + net_buf_add_mem(buf, data, len); + net_buf_put(&tx_queue, buf); +} + +static void recv_acl(const uint8_t *data, size_t len) +{ + const struct bt_hci_acl_hdr *hdr = (const struct bt_hci_acl_hdr *)data; + struct net_buf *buf; + + if (len < sizeof(*hdr)) { + LOG_ERR("Not enough data for ACL header."); + return; + } + + if ((len - sizeof(*hdr)) != sys_le16_to_cpu(hdr->len)) { + LOG_ERR("ACL payload length does not match the remaining data length."); + return; + } + + buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); + if (!buf) { + LOG_ERR("No available ACL buffers."); + return; + } + + data += sizeof(*hdr); + len -= sizeof(*hdr); + + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer."); + net_buf_unref(buf); + return; + } + + LOG_DBG("Received HCI ACL packet (handle: %u, len: %u).", + sys_le16_to_cpu(hdr->handle), sys_le16_to_cpu(hdr->len)); + + net_buf_add_mem(buf, data, len); + net_buf_put(&tx_queue, buf); +} + +static void recv_iso(const uint8_t *data, size_t len) +{ + const struct bt_hci_iso_hdr *hdr = (const struct bt_hci_iso_hdr *)data; + struct net_buf *buf; + + if (len < sizeof(*hdr)) { + LOG_ERR("Not enough data for ISO header."); + return; + } + + if ((len - sizeof(*hdr)) != bt_iso_hdr_len(sys_le16_to_cpu(hdr->len))) { + LOG_ERR("ISO payload length does not match the remaining data length."); + return; + } + + buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_NO_WAIT, hdr, sizeof(*hdr)); + if (!buf) { + LOG_ERR("No available ISO buffers."); + return; + } + + data += sizeof(*hdr); + len -= sizeof(*hdr); + + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer."); + net_buf_unref(buf); + return; + } + + LOG_DBG("Received HCI ISO packet (handle: %u, len: %u).", + sys_le16_to_cpu(hdr->handle), sys_le16_to_cpu(hdr->len)); + + net_buf_add_mem(buf, data, len); + net_buf_put(&tx_queue, buf); +} + +static void send(struct net_buf *buf, bool is_fatal_err) +{ + uint8_t type; + 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: + type = HCI_H4_ACL; + break; + case BT_BUF_EVT: + type = HCI_H4_EVT; + break; + case BT_BUF_ISO_IN: + type = HCI_H4_ISO; + break; + default: + LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); + net_buf_unref(buf); + return; + } + net_buf_push_u8(buf, type); + + 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) { + LOG_WRN("IPC send has been blocked during 10 retires."); + retries = 0; + } + + 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); +} + +static void bound(void *priv) +{ +#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 */ + + k_sem_give(&ipc_bound_sem); +} + +static void recv(const void *data, size_t len, void *priv) +{ + const uint8_t *tmp = (const uint8_t *)data; + enum hci_h4_type type; + + LOG_INF("Received hci message of %u bytes.", len); + LOG_HEXDUMP_DBG(data, len, "HCI data:"); + + type = (enum hci_h4_type)*tmp++; + len -= sizeof(type); + + switch (type) { + case HCI_H4_CMD: + recv_cmd(tmp, len); + break; + + case HCI_H4_ACL: + recv_acl(tmp, len); + break; + + case HCI_H4_ISO: + recv_iso(tmp, len); + break; + + default: + LOG_ERR("Unknown HCI type %u.", type); + return; + } +} + +static void tx_thread(void) +{ + struct net_buf *buf; + int err; + + while (1) { + buf = net_buf_get(&tx_queue, K_FOREVER); + err = bt_send(buf); + if (err) { + LOG_ERR("bt_send failed err: %d.", err); + net_buf_unref(buf); + } + + k_yield(); + } +} + +K_THREAD_DEFINE(tx_thread_id, CONFIG_BT_HCI_TX_STACK_SIZE, tx_thread, + NULL, NULL, NULL, + CONFIG_BT_HCI_TX_PRIO, 0, 0); + +static struct ipc_ept_cfg hci_ept_cfg = { + .name = "nrf_bt_hci", + .cb = { + .bound = bound, + .received = recv, + }, +}; + +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) +void bt_ctlr_assert_handle(char *file, uint32_t line) +{ + (void)irq_lock(); + + LOG_ERR("HCI Fatal error in: %s at %d.", file, line); + +#if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) + if (ipc_ept_ready) { + struct net_buf *buf; + + buf = hci_vs_err_assert(file, line); + if (!buf) { + send(buf, HCI_FATAL_MSG); + } else { + LOG_ERR("Can't send Fatal Error HCI event."); + } + } else { + LOG_ERR("HCI Fatal error before IPC endpoint is ready."); + } + +#else /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ + LOG_ERR("Controller assert in: %s at %d.", file, line); + +#endif /* !CONFIG_BT_HCI_VS_FATAL_ERROR */ + + for (;;) { + }; +} +#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) +{ + LOG_PANIC(); + + (void)irq_lock(); + + if ((!esf) && (ipc_ept_ready)) { + struct net_buf *buf; + + buf = hci_vs_err_stack_frame(reason, esf); + if (!buf) { + send(buf, HCI_FATAL_MSG); + } else { + LOG_ERR("Can't create Fatal Error HCI event."); + } + } + + for (;;) { + }; + + CODE_UNREACHABLE; +} +#endif /* CONFIG_BT_HCI_VS_FATAL_ERROR */ + +int ipc_bt_init(void) +{ + int err; + const struct device *hci_ipc_instance = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); + + LOG_INF("Initializing ipc_radio bt_hci."); + + err = bt_enable_raw(&rx_queue); + if (err) { + LOG_ERR("bt_enable_raw failed: %d.", err); + return err; + } + + err = ipc_service_open_instance(hci_ipc_instance); + if ((err < 0) && (err != -EALREADY)) { + LOG_ERR("IPC service instance initialization failed: %d.", err); + return err; + } + + err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); + if (err) { + LOG_ERR("Registering endpoint failed: %d.", err); + return err; + } + + return 0; +} + +int ipc_bt_process(void) +{ + struct net_buf *buf; + + k_sem_take(&ipc_bound_sem, K_FOREVER); + + while (1) { + buf = net_buf_get(&rx_queue, K_FOREVER); + send(buf, HCI_REGULAR_MSG); + } + + return 0; +} diff --git a/applications/ipc_radio/src/ipc_bt.h b/applications/ipc_radio/src/ipc_bt.h new file mode 100644 index 00000000000..c24d554333f --- /dev/null +++ b/applications/ipc_radio/src/ipc_bt.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef IPC_BT_H_ +#define IPC_BT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Initialize the IPC Bluetooth interface. + * + * The function might not have any functionality if the interface + * does not need to be initialized (or is initialized automatically). + * When this function is not needed, it should be implemented as an empty + * function and return -ENOSYS. + * + * @retval -ENOSYS The function is not implemented. + * @return 0 in case of success or negative value in case of error. + */ +int ipc_bt_init(void); + +/** @brief Give processing time to the IPC Bluetooth interface. + * + * The function might not have any functionality if the interface + * does not need to be given processing time (or is processed automatically). + * When this function is not needed, it should be implemented as an empty + * function and return -ENOSYS. + * + * @retval -ENOSYS The function is not implemented. + * @return 0 in case of success or negative value in case of error. + */ +int ipc_bt_process(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IPC_BT_H_ */ diff --git a/applications/ipc_radio/src/main.c b/applications/ipc_radio/src/main.c new file mode 100644 index 00000000000..fb058ca5736 --- /dev/null +++ b/applications/ipc_radio/src/main.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +#include "ipc_bt.h" + +LOG_MODULE_REGISTER(ipc_radio, CONFIG_IPC_RADIO_LOG_LEVEL); + +#if !(CONFIG_IPC_RADIO_802154 || CONFIG_IPC_RADIO_BT) +#error "No radio serialization selected." +#endif + +int main(void) +{ + int err; + + err = ipc_bt_init(); + if ((err) && (err != -ENOSYS)) { + LOG_ERR("Error initializing ipc radio %d", err); + return err; + } + + for (;;) { + err = ipc_bt_process(); + + if (err == -ENOSYS) { + /* Particular implementation does not need the process function */ + return 0; + } else if (err) { + LOG_ERR("Error processing ipc radio %d", err); + return err; + } + } +} diff --git a/applications/machine_learning/README.rst b/applications/machine_learning/README.rst index 78c95711c15..a25a98417e6 100644 --- a/applications/machine_learning/README.rst +++ b/applications/machine_learning/README.rst @@ -98,7 +98,7 @@ In the nRF Machine Learning application, application modules are automatically s The application uses :ref:`caf_power_manager` for this purpose. This means that Zephyr power management is forced to the :c:enumerator:`PM_STATE_ACTIVE` state when the device is in either the Power management active or the Power management suspended state, but the power off state is forced directly by :ref:`caf_power_manager` as Zephyr's :c:enumerator:`PM_STATE_SOFT_OFF` state. -* In the :c:enumerator:`POWER_MANAGER_LEVEL_ALIVE` state, the device is in working condition, Bluetooth is advertising whenever required and all the connections are maintained. +* In the :c:enumerator:`POWER_MANAGER_LEVEL_ALIVE` state, the device is in working condition, Bluetooth® is advertising whenever required and all the connections are maintained. * In the :c:enumerator:`POWER_MANAGER_LEVEL_SUSPENDED` state, the device maintains the active Bluetooth connection. * In the :c:enumerator:`POWER_MANAGER_LEVEL_OFF` state, the CPU is switched to the off mode. @@ -132,7 +132,7 @@ The figure visualizes relations between Application Event Manager, modules, driv Since the application architecture is uniform and the code is shared, the set of modules in use depends on configuration. In other words, not all of the modules need to be enabled for a given reference design. -For example, the :ref:`caf_ble_state` and :ref:`caf_ble_adv` modules are not enabled if the configuration does not use Bluetooth®. +For example, the :ref:`caf_ble_state` and :ref:`caf_ble_adv` modules are not enabled if the configuration does not use Bluetooth. See :ref:`nrf_machine_learning_app_internal_modules` for detailed information about every module used by the nRF Machine Learning application. @@ -153,7 +153,7 @@ If you build this application for the nRF53 DK, it enables additional features s See :ref:`ug_thingy53` for detailed information about the mentioned features. The nRF53 DK has a J-Link debug IC that can be used to program the firmware. -Alternatively, firmware can be updated over MCUBoot serial recovery or DFU over-the-air using Simple Management Protocol over Bluetooth. +Alternatively, firmware can be updated over MCUboot serial recovery or DFU over-the-air using Simple Management Protocol over Bluetooth. Keep in mind that if you use bootloader to update firmware, the new firmware must be compatible with used bootloader and partition map. The nRF53 Development Kit uses RTT as logger's backend. @@ -285,7 +285,7 @@ For example, the configuration files for the Thingy:53 are defined in the :file: The following configuration files can be defined for any supported board: -* :file:`prj_build_type.conf` - Kconfig configuration file for a build type. +* :file:`prj_.conf` - Kconfig configuration file for a :ref:`custom build type `. To support a given build type for the selected board, you must define the configuration file with a proper name. See :ref:`nrf_machine_learning_app_configuration_build_types` for more information. * :file:`app.overlay` - DTS overlay file specific for the board. @@ -311,8 +311,8 @@ The Thingy:53 and nRF53 Development Kit use multi-image build with the following * Bluetooth HCI RPMsg You can define the application-specific configuration for the mentioned child images in the board-specific directory in the :file:`applications/machine_learning/configuration/` directory. -The Kconfig configuration file should be located in subdirectory :file:`child_image/child_image_name` and its name should match the application Kconfig file name, that is contain the build type if necessary -For example, the :file:`applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf` file defines configuration of Bluetooth HCI RPMsg for ``debug`` build type on ``thingy53_nrf5340_cpuapp`` board, while the :file:`applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf` file defines configuration of Bluetooth HCI RPMsg for ``release`` build type. +The Kconfig configuration file should be located in subdirectory :file:`child_image/` and its name should match the application Kconfig file name, and it should contain the build type if necessary. +For example, the :file:`applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf` file defines configuration of Bluetooth HCI RPMsg for the ``debug`` build type on ``thingy53_nrf5340_cpuapp`` board, while the :file:`applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf` file defines configuration of Bluetooth HCI RPMsg for the ``release`` build type. See :ref:`ug_multi_image` for detailed information about multi-image builds and child image configuration. .. _nrf_machine_learning_app_requirements_build_types: @@ -322,10 +322,10 @@ nRF Machine Learning build types ================================ The nRF Machine Learning application does not use a single :file:`prj.conf` file. -Before you start testing the application, you can select one of the build types supported by the application, depending on your development kit and the building method. +Before you start testing the application, you can select one of the build types supported by the application. Not every board supports both mentioned build types. -See :ref:`app_build_additions_build_types` and :ref:`modifying_build_types` for more information about this feature of the |NCS|. +See :ref:`app_build_additions_build_types` and :ref:`cmake_options` for more information. The application supports the following build types: @@ -337,11 +337,10 @@ The application supports the following build types: - File name - Supported board - Description - * - Debug + * - Debug (default) - :file:`prj.conf` - All from `Requirements`_ - - | Debug version of the application; can be used to verify if the application works correctly. - | Used by default if no build type is explicitly selected. + - Debug version of the application; can be used to verify if the application works correctly. * - Release - :file:`prj_release.conf` - ``nrf52840dk_nrf52840`` @@ -368,14 +367,14 @@ Building the default configurations requires an Internet connection, because the Selecting a build type ====================== -Before you start testing the application, you can select one of the :ref:`nrf_machine_learning_app_requirements_build_types`, depending on your development kit and building method. -See :ref:`modifying_build_types` for detailed steps how to select a build type. +Before you start testing the application, you can select one of the :ref:`nrf_machine_learning_app_requirements_build_types`. +See :ref:`cmake_options` for information about how to select a build type. Providing API key ================= If the URI of the Edge Impulse zip file requires providing an additional API key, you can provide it using the following CMake definition: :c:macro:`EI_API_KEY_HEADER`. -This definition is set in a similar way as selected build type. +This definition is set in a similar way as selecting a build type. For more detailed information about building the machine learning model in the |NCS|, see :ref:`ug_edge_impulse`. .. tip:: @@ -425,16 +424,16 @@ After programming the application, perform the following steps to test the nRF M After the mode is switched, the LED color changes to red and the LED starts blinking very slowly. #. Program the :ref:`central_uart` sample to a compatible development kit, for example the nRF52840 Development Kit. #. Turn on the programmed device. - After a brief delay, the Bluetooth® connection between the sample and the Thingy is established. + After a brief delay, the Bluetooth connection between the sample and the Thingy is established. The Thingy forwards the sensor readouts over NUS. The LED on the Thingy starts to blink rapidly. -#. Connect to the Bluetooth® Central UART sample with a terminal emulator (for example, PuTTY). - See :ref:`putty` for the required settings. +#. Connect to the Bluetooth Central UART sample with a terminal emulator (for example, `nRF Connect Serial Terminal`_). + See :ref:`test_and_optimize` for the required settings. #. Observe the sensor readouts represented as comma-separated values. Every line represents a single sensor readout. The Thingy forwards sensor readouts over NUS to the Central UART sample. The sample forwards the data to the host over UART. -#. Turn off PuTTY to ensure that only one program has access to data on UART. +#. Turn off the terminal emulator to ensure that only one program has access to data on UART. Optionally, you can also connect to the device using `Edge Impulse's data forwarder`_ and forward data to `Edge Impulse studio`_ (after logging in). See `Forwarding data to Edge Impulse studio`_ for details. @@ -457,11 +456,11 @@ After programming the application, perform the following steps to test the nRF M This signal is marked as anomaly by the machine learning model and **LED1** starts breathing. #. Press and hold **Button 1** for more than 5 seconds to switch to the data forwarding mode. After the mode is switched, **LED1** starts to blink rapidly. -#. Connect to the development kit with a terminal emulator (for example, PuTTY). - See :ref:`putty` for the required settings. +#. Connect to the development kit with a terminal emulator (for example, `nRF Connect Serial Terminal`_). + See :ref:`test_and_optimize` for the required settings. #. Observe the sensor readouts represented as comma-separated values. Every line represents a single sensor readout. -#. Turn off PuTTY to ensure that only one program will access data on UART. +#. Turn off the terminal emulator to ensure that only one program will access data on UART. Optionally, you can also connect to the device using `Edge Impulse's data forwarder`_ and forward data to `Edge Impulse studio`_ (after logging in). See `Forwarding data to Edge Impulse studio`_ for details. @@ -493,6 +492,8 @@ To start forwarding data to Edge Impulse studio: Sampling example +.. _nrf_machine_learning_app_porting_guide: + Porting guide ************* diff --git a/applications/machine_learning/VERSION b/applications/machine_learning/VERSION index 956d85eaac4..808984a04c5 100644 --- a/applications/machine_learning/VERSION +++ b/applications/machine_learning/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 2 -VERSION_MINOR = 5 -PATCHLEVEL = 0 +VERSION_MINOR = 6 +PATCHLEVEL = 99 VERSION_TWEAK = 0 EXTRAVERSION = diff --git a/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf b/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf index 1c128850e7b..3aeb468fb22 100644 --- a/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf +++ b/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf @@ -27,3 +27,6 @@ CONFIG_BT_BUF_ACL_RX_SIZE=502 CONFIG_ASSERT=y CONFIG_DEBUG_INFO=y CONFIG_EXCEPTION_STACK_TRACE=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/mcuboot/prj.conf b/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/mcuboot/prj.conf index df64b91d5d2..47d9a7d722c 100644 --- a/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/mcuboot/prj.conf +++ b/applications/machine_learning/configuration/nrf5340dk_nrf5340_cpuapp/child_image/mcuboot/prj.conf @@ -49,7 +49,6 @@ CONFIG_USE_SEGGER_RTT=n CONFIG_LOG=n CONFIG_ERRNO=n CONFIG_PRINTK=n -CONFIG_RESET_ON_FATAL_ERROR=n # The following configurations are required to support simultaneous multi image update CONFIG_PCD_APP=y @@ -67,3 +66,6 @@ CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf index 79bc6a880b9..ad7ec774cb5 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf @@ -22,3 +22,6 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_ASSERT=y CONFIG_DEBUG_INFO=y CONFIG_EXCEPTION_STACK_TRACE=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf index d0d434c677d..1eee4d1a5cc 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf @@ -18,3 +18,6 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_BUF_CMD_TX_COUNT=10 + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_rtt.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_rtt.conf index 79bc6a880b9..ad7ec774cb5 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_rtt.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_rtt.conf @@ -22,3 +22,6 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_ASSERT=y CONFIG_DEBUG_INFO=y CONFIG_EXCEPTION_STACK_TRACE=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj.conf index 79bc6a880b9..ad7ec774cb5 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj.conf @@ -22,3 +22,6 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_ASSERT=y CONFIG_DEBUG_INFO=y CONFIG_EXCEPTION_STACK_TRACE=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_release.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_release.conf index d0d434c677d..1eee4d1a5cc 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_release.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_release.conf @@ -18,3 +18,6 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_BUF_CMD_TX_COUNT=10 + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_rtt.conf b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_rtt.conf index 79bc6a880b9..ad7ec774cb5 100644 --- a/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_rtt.conf +++ b/applications/machine_learning/configuration/thingy53_nrf5340_cpuapp_ns/child_image/hci_ipc/prj_rtt.conf @@ -22,3 +22,6 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_ASSERT=y CONFIG_DEBUG_INFO=y CONFIG_EXCEPTION_STACK_TRACE=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/machine_learning/src/events/ml_result_event.c b/applications/machine_learning/src/events/ml_result_event.c index 146ee5f0e1e..ca19b38ac68 100644 --- a/applications/machine_learning/src/events/ml_result_event.c +++ b/applications/machine_learning/src/events/ml_result_event.c @@ -14,7 +14,7 @@ static void log_ml_result_event(const struct app_event_header *aeh) const struct ml_result_event *event = cast_ml_result_event(aeh); APP_EVENT_MANAGER_LOG(aeh, "%s val: %0.2f anomaly: %0.2f", - event->label, event->value, event->anomaly); + event->label, (double)event->value, (double)event->anomaly); } static void profile_ml_result_event(struct log_event_buf *buf, diff --git a/applications/machine_learning/src/modules/led_state.c b/applications/machine_learning/src/modules/led_state.c index 37498f81413..5a92dc01c9e 100644 --- a/applications/machine_learning/src/modules/led_state.c +++ b/applications/machine_learning/src/modules/led_state.c @@ -24,8 +24,8 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_ML_APP_LED_STATE_LOG_LEVEL); #define DISPLAY_SIM_SIGNAL IS_ENABLED(CONFIG_ML_APP_SENSOR_SIM_EVENTS) #define DISPLAY_DATA_FORWARDER IS_ENABLED(CONFIG_ML_APP_EI_DATA_FORWARDER_EVENTS) -#define ANOMALY_THRESH (CONFIG_ML_APP_LED_STATE_ANOMALY_THRESH / 1000.0) -#define VALUE_THRESH (CONFIG_ML_APP_LED_STATE_VALUE_THRESH / 1000.0) +#define ANOMALY_THRESH (CONFIG_ML_APP_LED_STATE_ANOMALY_THRESH / 1000.0f) +#define VALUE_THRESH (CONFIG_ML_APP_LED_STATE_VALUE_THRESH / 1000.0f) #define PREDICTION_STREAK_THRESH CONFIG_ML_APP_LED_STATE_PREDICTION_STREAK_THRESH BUILD_ASSERT(PREDICTION_STREAK_THRESH > 0); diff --git a/applications/machine_learning/src/modules/ml_runner.c b/applications/machine_learning/src/modules/ml_runner.c index c35259f88d5..e405408f881 100644 --- a/applications/machine_learning/src/modules/ml_runner.c +++ b/applications/machine_learning/src/modules/ml_runner.c @@ -67,8 +67,10 @@ static void submit_result(void) int err = ei_wrapper_get_next_classification_result(&evt->label, &evt->value, NULL); - if (!err) { + if (!err && ei_wrapper_classifier_has_anomaly()) { err = ei_wrapper_get_anomaly(&evt->anomaly); + } else { + evt->anomaly = 0.0; } __ASSERT_NO_MSG(!err); diff --git a/applications/matter_bridge/CMakeLists.txt b/applications/matter_bridge/CMakeLists.txt index 3d54988e737..266e83e752d 100644 --- a/applications/matter_bridge/CMakeLists.txt +++ b/applications/matter_bridge/CMakeLists.txt @@ -10,56 +10,41 @@ cmake_minimum_required(VERSION 3.20.0) set(mcuboot_KCONFIG_ROOT "\\\${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.mcuboot.root") set(hci_ipc_KCONFIG_ROOT "\\\${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.hci_ipc.root") -# For prj.conf the CONF_FILE is empty. In other case extract the exact file name from the path string. -if(CONF_FILE) - get_filename_component(CONFIG_FILE_NAME ${CONF_FILE} NAME) -endif() - -if(NOT CONFIG_FILE_NAME STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) project(matter-bridge) -set(COMMON_ROOT ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common) -set(NLIO_ROOT ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/third_party/nlio/repo) +# Enable GNU STD support and initialize the Matter Data Model. include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/app/enable-gnu-std.cmake) include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/src/app/chip_data_model.cmake) # NORDIC SDK APP START + +# Include all source files that are located in the Matter common directory. +include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/source_common.cmake) + target_include_directories(app PRIVATE src src/bridged_device_types - ${COMMON_ROOT}/src - ${COMMON_ROOT}/src/bridge/ - ${COMMON_ROOT}/src/bridge/util - ${NLIO_ROOT}/include - ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/zzz_generated/app-common + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/ + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/util ) target_sources(app PRIVATE src/app_task.cpp src/main.cpp src/bridge_shell.cpp - ${COMMON_ROOT}/src/bridge/bridge_manager.cpp - ${COMMON_ROOT}/src/bridge/matter_bridged_device.cpp - ${COMMON_ROOT}/src/bridge/bridge_storage_manager.cpp - ${COMMON_ROOT}/src/bridge/bridged_device_data_provider.cpp - ${COMMON_ROOT}/src/binding/binding_handler.cpp - src/zap-generated/IMClusterCommandHandler.cpp - src/zap-generated/callback-stub.cpp - ${COMMON_ROOT}/src/led/led_widget.cpp - ${COMMON_ROOT}/src/ps_storage/persistent_storage_util.cpp - ${COMMON_ROOT}/src/tasks/task_executor.cpp - ${COMMON_ROOT}/src/board/board.cpp - ${COMMON_ROOT}/src/init/matter_init.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridge_manager.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/matter_bridged_device.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridge_storage_manager.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/bridged_device_data_provider.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/binding/binding_handler.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/persistent_storage/persistent_storage_util.cpp ) if(CONFIG_BRIDGED_DEVICE_BT) target_sources(app PRIVATE - ${COMMON_ROOT}/src/bridge/ble_connectivity_manager.cpp + ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/ble_connectivity_manager.cpp src/ble_providers/ble_bridged_device_factory.cpp ) target_include_directories(app PRIVATE src/ble_providers) @@ -145,14 +130,6 @@ endif() # CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE endif() # CONFIG_BRIDGED_DEVICE_BT -if(CONFIG_CHIP_OTA_REQUESTOR OR CONFIG_MCUMGR_TRANSPORT_BT) - target_sources(app PRIVATE ${COMMON_ROOT}/src/dfu/ota/ota_util.cpp) -endif() - -if(CONFIG_MCUMGR_TRANSPORT_BT) - target_sources(app PRIVATE ${COMMON_ROOT}/src/dfu/smp/dfu_over_smp.cpp) -endif() - chip_configure_data_model(app INCLUDE_SERVER BYPASS_IDL diff --git a/applications/matter_bridge/Kconfig b/applications/matter_bridge/Kconfig index 8e274aa4678..eae983839c0 100644 --- a/applications/matter_bridge/Kconfig +++ b/applications/matter_bridge/Kconfig @@ -98,6 +98,30 @@ config BT_GATT_CLIENT config BT_GATT_DM default y +config BT_EXT_ADV + default y + +config BT_SMP + default y + +if BT_SMP + +config BT_SETTINGS + default y + +# Configure how many Bluetooth LE devices will be paired with Matter bridge. Assuming it will be only bridged devices, it should be set to BT_MAX_CONN - 1. +config BT_MAX_PAIRED + default 2 + +# Use two Bluetooth LE identities. The first one is used by the peripheral for Matter service advertising purposes, and the other is used by the Matter bridge central. +config BT_ID_MAX + default 2 + +config BT_EXT_ADV_LEGACY_SUPPORT + default y + +endif + config BRIDGE_BLE_DEVICE_POLLING_INTERVAL int "BLE humidity measurement readout polling interval in ms" default 3000 @@ -128,15 +152,12 @@ config BRIDGE_HUMIDITY_SENSOR_MAX_MEASURED_VALUE endif -config EXPERIMENTAL - default y - # Enable Read Client functionality for all build configurations. config CHIP_ENABLE_READ_CLIENT default y source "${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.features" source "${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.defaults" -source "${ZEPHYR_BASE}/../nrf/samples/matter/common/src/bridge/Kconfig" -source "${ZEPHYR_BASE}/../nrf/samples/matter/common/src/Kconfig" +source "${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/bridge/Kconfig" +source "${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/Kconfig" source "Kconfig.zephyr" diff --git a/applications/matter_bridge/Kconfig.sysbuild b/applications/matter_bridge/Kconfig.sysbuild index 9e53f4f992f..6f2a4ce803a 100644 --- a/applications/matter_bridge/Kconfig.sysbuild +++ b/applications/matter_bridge/Kconfig.sysbuild @@ -5,17 +5,37 @@ # config NRF_DEFAULT_BLUETOOTH - default y if ($(BOARD) = "nrf7002dk_nrf5340_cpuapp") + default y if ("$(BOARD)" = "nrf7002dk_nrf5340_cpuapp") || ("$(BOARD)" = "nrf5340dk_nrf5340_cpuapp") choice BOOTLOADER default BOOTLOADER_MCUBOOT endchoice -if BOOTLOADER_MCUBOOT && ($(BOARD) = "nrf7002dk_nrf5340_cpuapp") +if BOOTLOADER_MCUBOOT && (("$(BOARD)" = "nrf5340dk_nrf5340_cpuapp") || ("$(BOARD)" = "nrf7002dk_nrf5340_cpuapp")) + +if ("$(BOARD)" = "nrf5340dk_nrf5340_cpuapp") + +config NRF_WIFI_PATCHES_EXT_FLASH_STORE + default y + +config NRF_WIFI_FW_PATCH_DFU + default y + +config MCUBOOT_UPDATEABLE_IMAGES + default 3 + +config DFU_MULTI_IMAGE_MAX_IMAGE_COUNT + default 3 + +endif + +if ($(BOARD) = "nrf7002dk_nrf5340_cpuapp") config MCUBOOT_UPDATEABLE_IMAGES default 2 +endif + choice MCUBOOT_MODE default MCUBOOT_MODE_OVERWRITE_ONLY endchoice diff --git a/applications/matter_bridge/README.rst b/applications/matter_bridge/README.rst index b8b57a207ce..94835b3e573 100644 --- a/applications/matter_bridge/README.rst +++ b/applications/matter_bridge/README.rst @@ -9,6 +9,14 @@ The devices on the non-Matter side of the Matter bridge are called *bridged devi The Matter bridge device works as a Matter accessory device, meaning it can be paired and controlled remotely over a Matter network built on top of a low-power 802.11ax (Wi-Fi 6) network. +Currently the Matter bridge application supports the following types of *bridged devices*: + +* Bluetooth® LE peripheral devices - Devices that operate on real data (such as sensor measurements or lighting state). +* Simulated devices - Devices that interact with the bridge by using data fabricated programmatically by the software. + +Note that, in addition to already implemented *bridged devices*, the Matter bridge architecture allows you to add support for other devices that run over diverse connectivity technologies, such as Zigbee or Bluetooth® Mesh. +To learn more details about supported *bridged devices*, refer to the :ref:`Bridged device support ` section of Matter bridge application guide. + See the subpages for how to use the application and how to extend it. .. toctree:: diff --git a/applications/matter_bridge/VERSION b/applications/matter_bridge/VERSION new file mode 100644 index 00000000000..808984a04c5 --- /dev/null +++ b/applications/matter_bridge/VERSION @@ -0,0 +1,5 @@ +VERSION_MAJOR = 2 +VERSION_MINOR = 6 +PATCHLEVEL = 99 +VERSION_TWEAK = 0 +EXTRAVERSION = diff --git a/applications/matter_bridge/boards/nrf5340dk_nrf5340_cpuapp.overlay b/applications/matter_bridge/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..20a9383a630 --- /dev/null +++ b/applications/matter_bridge/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + +/* Set IPC thread priority to the highest value to not collide with other threads. */ +&ipc0 { + zephyr,priority = <0 PRIO_COOP>; +}; + +/* Disable unused peripherals to reduce power consumption */ +&adc { + status = "disabled"; +}; +&i2c1 { + status = "disabled"; +}; +&pwm0 { + status = "disabled"; +}; +&spi2 { + status = "disabled"; +}; +&usbd { + status = "disabled"; +}; diff --git a/applications/matter_bridge/child_image/hci_ipc/prj.conf b/applications/matter_bridge/child_image/hci_ipc/prj.conf index 4df8ed0ec19..3a23f561115 100644 --- a/applications/matter_bridge/child_image/hci_ipc/prj.conf +++ b/applications/matter_bridge/child_image/hci_ipc/prj.conf @@ -17,3 +17,4 @@ CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_BT_MAX_CONN=10 CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y diff --git a/applications/matter_bridge/child_image/hci_ipc/prj_release.conf b/applications/matter_bridge/child_image/hci_ipc/prj_release.conf index df6cc827316..029f7086739 100644 --- a/applications/matter_bridge/child_image/hci_ipc/prj_release.conf +++ b/applications/matter_bridge/child_image/hci_ipc/prj_release.conf @@ -17,3 +17,4 @@ CONFIG_RESET_ON_FATAL_ERROR=y CONFIG_BT_MAX_CONN=10 CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y diff --git a/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..18f34a962ea --- /dev/null +++ b/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay new file mode 100644 index 00000000000..18f34a962ea --- /dev/null +++ b/applications/matter_bridge/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst b/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst index 2290a1b2b31..c811ccc5ce5 100644 --- a/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst +++ b/applications/matter_bridge/doc/adding_ble_bridged_device_service.rst @@ -30,9 +30,9 @@ The following steps show how to add support for a new Bluetooth LE service calle #. Implement the ``Bridged Device Data Provider`` role. a. Create the :file:`my_bt_service_data_provider.cpp` and :file:`my_bt_service_data_provider.h` files for your Bluetooth LE Data Provider in the :file:`src/ble_providers` directory. - #. Open the :file:`nrf/samples/matter/common/bridge/ble_bridged_device.h` header file and find the :c:struct:`BLEBridgedDeviceProvider` class constructor. + #. Open the :file:`nrf/samples/matter/common/src/bridge/ble_bridged_device.h` header file and find the :c:struct:`BLEBridgedDeviceProvider` class constructor. Note the constructor signature, it will be used in the child class implemented in the next steps. - #. Add a new :c:struct:`MyBtServiceDataProvider` class inheriting :c:struct:`BLEBridgedDeviceProvider`, and implement its constructor in the :file:`my_bt_service_data_provider.cpp` and :file:`my_bt_service_data_provider.h` files. + #. Add a new :c:struct:`MyBtServiceDataProvider` class inheriting :c:struct:`BLEBridgedDeviceProvider`, and implement its constructor in the :file:`my_bt_service_data_provider.h` file. .. code-block:: C++ @@ -42,13 +42,13 @@ The following steps show how to add support for a new Bluetooth LE service calle #include "my_bt_service.h" - class MyBtServiceDataProvider : public BLEBridgedDeviceProvider { + class MyBtServiceDataProvider : public Nrf::BLEBridgedDeviceProvider { public: - explicit MyBtServiceDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BLEBridgedDeviceProvider(updateCallback, commandCallback) {} + explicit MyBtServiceDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BLEBridgedDeviceProvider(updateCallback, commandCallback) {} }; - #. Open the :file:`nrf/samples/matter/common/bridge/ble_bridged_device.h` header file again to see which methods of :c:struct:`BLEBridgedDeviceProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`MyBtServiceDataProvider` class. + #. Open the :file:`nrf/samples/matter/common/src/bridge/ble_bridged_device.h` header file again to see which methods of :c:struct:`BLEBridgedDeviceProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`MyBtServiceDataProvider` class. Note that :c:struct:`BLEBridgedDeviceProvider` inherits from the :c:struct:`BridgedDeviceDataProvider` class, so the :c:struct:`MyBtServiceDataProvider` class has to implement the purely virtual methods of :c:struct:`BridgedDeviceDataProvider` as well. #. Edit the :c:struct:`MyBtServiceDataProvider` class in the :file:`my_bt_service_data_provider.h` header file to declare the required methods as follows: @@ -62,6 +62,20 @@ The following steps show how to add support for a new Bluetooth LE service calle bt_uuid *GetServiceUuid() override; int ParseDiscoveredData(bt_gatt_dm *discoveredData) override; + #. Include the necessary header files and namespaces in the :file:`my_bt_service_data_provider.cpp` file: + + .. code-block:: C++ + + #include "my_bt_service_data_provider.h" + + #include + #include + #include + + using namespace ::chip; + using namespace ::chip::app; + using namespace Nrf; + #. Implement the body of the :c:func:`Init` method so that it can prepare the data provider for further operation. If there are no additional actions to be done before starting the provider, it can be implemented in the :file:`my_bt_service_data_provider.cpp` file as empty. @@ -226,7 +240,7 @@ The following steps show how to add support for a new Bluetooth LE service calle return bt_gatt_subscribe(mDevice.mConn, &mGattSubscribeParams); } -#. Add the ``MyBtServiceDataProvider`` implementation created in a previous steps to the compilation process. +#. Add the ``MyBtServiceDataProvider`` implementation created in a previous step to the compilation process. To do that, edit the :file:`CMakeLists.txt` file as follows: .. code-block:: cmake diff --git a/applications/matter_bridge/doc/adding_bridged_matter_device.rst b/applications/matter_bridge/doc/adding_bridged_matter_device.rst index 6b283b7c1c7..99417a32b41 100644 --- a/applications/matter_bridge/doc/adding_bridged_matter_device.rst +++ b/applications/matter_bridge/doc/adding_bridged_matter_device.rst @@ -18,7 +18,7 @@ The following steps show how to add support for a new Matter device type, using #. Implement the ``Matter Bridged Device`` role. a. Create the :file:`pressure_sensor.cpp` and :file:`pressure_sensor.h` files in the :file:`src/bridged_device_types` directory. - #. Open the :file:`nrf/samples/matter/common/bridge/matter_bridged_device.h` header file and find the :c:struct:`MatterBridgedDevice` class constructor. + #. Open the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file and find the :c:struct:`MatterBridgedDevice` class constructor. Note the constructor signature, it will be used in the child class implemented in the next steps. #. Add a new :c:struct:`PressureSensorDevice` class inheriting :c:struct:`MatterBridgedDevice`, and implement its constructor in the :file:`pressure_sensor.cpp` and :file:`pressure_sensor.h` files. @@ -30,7 +30,7 @@ The following steps show how to add support for a new Matter device type, using #include "matter_bridged_device.h" - class PressureSensorDevice : public MatterBridgedDevice { + class PressureSensorDevice : public Nrf::MatterBridgedDevice { public: PressureSensorDevice(const char *nodeLabel); @@ -48,7 +48,7 @@ The following steps show how to add support for a new Matter device type, using #. Declare all clusters that are mandatory for the Pressure Sensor device type, according to the Matter device library specification, and fill the appropriate :c:struct:`MatterBridgedDevice` class fields in the :c:struct:`PressureSensorDevice` class constructor. - The Pressure Sensor device requires the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which can be declared using helper macros from the :file:`nrf/samples/matter/common/bridge/matter_bridged_device.h` header file, and the ``Pressure Measurement`` cluster, which has to be defined in the application. + The Pressure Sensor device requires the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which can be declared using helper macros from the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file, and the ``Pressure Measurement`` cluster, which has to be defined in the application. Edit the :file:`pressure_sensor.cpp` file as follows: - Add: @@ -63,6 +63,7 @@ The following steps show how to add support for a new Matter device type, using }; /* namespace */ using namespace ::chip; using namespace ::chip::app; + using namespace Nrf; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(pressureSensorAttrs) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::PressureMeasurement::Attributes::MeasuredValue::Id, INT16S, 2, 0), @@ -106,7 +107,7 @@ The following steps show how to add support for a new Matter device type, using mDataVersion = static_cast(chip::Platform::MemoryAlloc(sizeof(DataVersion) * mDataVersionSize)); } - #. Open the :file:`nrf/samples/matter/common/bridge/matter_bridged_device.h` header file again to see which methods of the :c:struct:`MatterBridgedDevice` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`PressureSensorDevice` class. + #. Open the :file:`nrf/samples/matter/common/src/bridge/matter_bridged_device.h` header file again to see which methods of the :c:struct:`MatterBridgedDevice` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`PressureSensorDevice` class. #. Edit the :c:struct:`PressureSensorDevice` class in the :file:`pressure_sensor.h` header file to declare the required methods as follows: .. code-block:: C++ @@ -254,7 +255,7 @@ The following steps show how to add support for a new Matter device type, using #. Implement the ``Bridged Device Data Provider`` role. a. Create the :file:`simulated_pressure_sensor_data_provider.cpp` and :file:`simulated_pressure_sensor_data_provider.h` files in the :file:`src/simulated_providers` directory. - #. Open the :file:`nrf/samples/matter/common/bridge/bridged_device_data_provider.h` header file and find the :c:struct:`BridgedDeviceDataProvider` class constructor. + #. Open the :file:`nrf/samples/matter/common/src/bridge/bridged_device_data_provider.h` header file and find the :c:struct:`BridgedDeviceDataProvider` class constructor. Note the constructor signature, it will be used in the child class implemented in the next steps. #. Add a new :c:struct:`SimulatedPressureSensorDataProvider` class inheriting :c:struct:`BridgedDeviceDataProvider`, and implement its constructor in the :file:`simulated_pressure_sensor_data_provider.h` header file. @@ -266,13 +267,13 @@ The following steps show how to add support for a new Matter device type, using #include - class SimulatedPressureSensorDataProvider : public BridgedDeviceDataProvider { + class SimulatedPressureSensorDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedPressureSensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + SimulatedPressureSensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) {} ~SimulatedPressureSensorDataProvider() {} }; - #. Open the :file:`nrf/samples/matter/common/bridge/bridged_device_data_provider.h` header file again to see which methods of the :c:struct:`BridgedDeviceDataProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`SimulatedPressureSensorDataProvider` class. + #. Open the :file:`nrf/samples/matter/common/src/bridge/bridged_device_data_provider.h` header file again to see which methods of the :c:struct:`BridgedDeviceDataProvider` class are purely virtual (assigned with ``=0``) and have to be overridden by the :c:struct:`SimulatedPressureSensorDataProvider` class. #. Edit the :c:struct:`SimulatedPressureSensorDataProvider` class in the :file:`simulated_pressure_sensor_data_provider.h` header file to declare the required methods as follows: .. code-block:: C++ @@ -308,6 +309,7 @@ The following steps show how to add support for a new Matter device type, using using namespace ::chip; using namespace ::chip::app; + using namespace Nrf; void SimulatedPressureSensorDataProvider::Init() { @@ -387,19 +389,19 @@ The following steps show how to add support for a new Matter device type, using #include "pressure_sensor.h" #include "simulated_pressure_sensor_data_provider.h" - - :file:`src/simulated_providers/simulated_bridged_device_factory.h`, :c:func:`GetBridgedDeviceFactory` method + - :file:`src/simulated_providers/simulated_bridged_device_factory.cpp`, :c:func:`GetBridgedDeviceFactory` method .. code-block:: C++ { PressureSensorDevice::kPressureSensorDeviceTypeId, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } return chip::Platform::New(nodeLabel); } }, - - :file:`src/simulated_providers/simulated_bridged_device_factory.h`, :c:func:`GetDataProviderFactory` method + - :file:`src/simulated_providers/simulated_bridged_device_factory.cpp`, :c:func:`GetDataProviderFactory` method .. code-block:: C++ diff --git a/applications/matter_bridge/doc/matter_bridge_description.rst b/applications/matter_bridge/doc/matter_bridge_description.rst index 1035313ed1f..e9740fae1ce 100644 --- a/applications/matter_bridge/doc/matter_bridge_description.rst +++ b/applications/matter_bridge/doc/matter_bridge_description.rst @@ -126,7 +126,7 @@ By default, the Matter accessory device has no IPv6 network configured. To use the device within a Wi-Fi network, you must pair it with the Matter controller over Bluetooth® LE to get the configuration from the controller. The Bluetooth LE advertising starts automatically upon device startup, but only for a predefined period of time (15 minutes by default). -If the Bluetooth LE advertising times out, you can re-enable it manually by pressing **Button (SW2)**. +If the Bluetooth LE advertising times out, you can re-enable it manually by pressing **Button (SW1)**. Additionally, the controller must get the `Onboarding information`_ from the Matter accessory device and provision the device into the network. For details, see the `Testing`_ section. @@ -144,7 +144,7 @@ Button 1: * If pressed for less than three seconds: * If the device is not provisioned to the Matter network, it initiates the SMP server (Simple Management Protocol) and Bluetooth LE advertising for Matter commissioning. - After that, the Direct Firmware Update (DFU) over Bluetooth Low Energy can be started. + After that, the Device Firmware Update (DFU) over Bluetooth Low Energy can be started. (See `Updating the device firmware`_.) Bluetooth LE advertising makes the device discoverable over Bluetooth LE for the predefined period of time (15 minutes by default). @@ -155,6 +155,20 @@ Button 1: * If pressed for more than three seconds, it initiates the factory reset of the device. Releasing the button within a 3-second window of the initiation cancels the factory reset procedure. +.. include:: ../../../samples/matter/lock/README.rst + :start-after: matter_door_lock_sample_led1_start + :end-before: matter_door_lock_sample_led1_end + +LED 2: + If the :kconfig:option:`CONFIG_BRIDGED_DEVICE_BT` Kconfig option is set to ``y``, shows the current state of Bridge's Bluetooth LE connectivity. + The following states are possible: + + * Turned Off - The Bridge device is in the idle state and has no Bluetooth LE devices paired. + * Solid On - The Bridge device is in the idle state and all connections to the Bluetooth LE bridged devices are stable. + * Slow Even Flashing (1000 ms on / 1000 ms off) - The Bridge device lost connection to at least one Bluetooth LE bridged device. + * Even Flashing (300 ms on / 300 ms off) - The scan for Bluetooth LE devices is in progress. + * Fast Even Flashing (100 ms on / 100 ms off) - The Bridge device is connecting to the Bluetooth LE device and waiting for the Bluetooth LE authentication PIN code. + .. include:: ../../../samples/matter/lock/README.rst :start-after: matter_door_lock_sample_jlink_start :end-before: matter_door_lock_sample_jlink_end @@ -280,12 +294,49 @@ Adding a Bluetooth LE bridged device to the Matter bridge .. code-block:: console + ---------------------------------------------------------------------------------------- + | Bridged Bluetooth LE device authentication | + | | + | Insert pin code displayed by the Bluetooth LE peripheral device | + | to authenticate the pairing operation. | + | | + | To do that, use matter_bridge pincode shell command. | + ---------------------------------------------------------------------------------------- + + To complete the adding process, you must use the ``pincode`` command to insert the authentication pincode displayed by the bridged device. + +Inserting a Bluetooth LE authentication pincode + Use the following command: + + .. parsed-literal:: + :class: highlight + + matter_bridge pincode ** ** + + In this command: + + * ** is the Bluetooth LE device index on the list returned by the ``scan`` command. + * ** is the Bluetooth LE authentication pincode of the bridged device to be paired. + + Example command: + + .. code-block:: console + + uart:~$ matter_bridge pincode 0 305051 + + The terminal output is similar to the following one: + + .. code-block:: console + + I: Pairing completed: E3:9D:5E:51:AD:14 (random), bonded: 1 + + I: Security changed: level 4 + I: The GATT discovery completed I: Added device to dynamic endpoint 3 (index=0) I: Added device to dynamic endpoint 4 (index=1) I: Created 0x100 device type on the endpoint 3 I: Created 0xf device type on the endpoint 4 - Removing a bridged device from the Matter bridge Use the following command: @@ -349,20 +400,47 @@ Build the target using the following command in the project directory to enable .. parsed-literal:: :class: highlight - west build -b nrf7002dk_nrf5340_cpuapp -- -DCONFIG_BRIDGED_DEVICE_BT=y -DOVERLAY_CONFIG="overlay-bt_max_connections_app.conf" -Dhci_ipc_OVERLAY_CONFIG="*absoule_path*/overlay-bt_max_connections_net.conf" + west build -b nrf7002dk_nrf5340_cpuapp -- -DCONFIG_BRIDGED_DEVICE_BT=y -DEXTRA_CONF_FILE="overlay-bt_max_connections_app.conf" -Dhci_ipc_EXTRA_CONF_FILE="*absoule_path*/overlay-bt_max_connections_net.conf" Replace *absolute_path* with the absolute path to the Matter bridge application on your local disk. +Configuring the Bluetooth LE security +------------------------------------- + +The application uses Bluetooth LE Security Manager Protocol (SMP) to provide secure connection between the Matter bridge and Bluetooth LE bridged devices. + +.. note:: + Do not confuse the Bluetooth LE Security Manager Protocol (SMP) abbreviation with the Bluetooth LE Simple Management Protocol that has the same abbreviation and is used for the Device Firmware Upgrade process. + +The following security levels are defined by the Bluetooth LE specification: + +* Security Level 1 - supports communication without security. +* Security Level 2 - supports AES-CMAC communication encryption, but does not require device authentication. +* Security Level 3 - supports AES-CMAC communication encryption, requires device authentication and pairing. +* Security Level 4 - supports ECDHE communication encryption, requires authentication and pairing. + +To read more about the Bluetooth LE security implementation in Zephyr, see the Security section of the :ref:`bluetooth-arch` page. +By default, the Matter bridge application has SMP enabled and supports security levels 2, 3 and 4. + +You can disable the Bluetooth LE security mechanisms by setting the :kconfig:option:`CONFIG_BT_SMP` Kconfig option to ``n``. +This is strongly not recommended, as it leads to unencrypted communication with bridged devices, which makes them vulnerable to the security attacks. + +You can select the minimum security level required by the application. +When selected, the Matter bridge will require setting the selected minimum level from the connected Bluetooth LE bridged device. +If the bridged device supports also levels higher than the selected minimum, the devices may negotiate using the highest shared security level. +In case the bridged device does not support the minimum required level, the connection will be terminated. +To select the minimum security level, set the :kconfig:option:`CONFIG_BRIDGE_BT_MINIMUM_SECURITY_LEVEL` Kconfig option to ``2``, ``3`` or ``4``. + .. _matter_bridge_app_build_types: Matter bridge build types ========================= The Matter bridge application does not use a single :file:`prj.conf` file. -Before you start testing the application, you can select one of the build types supported by the application, depending on your development kit and the building method. +Before you start testing the application, you can select one of the build types supported by the application. Not every board supports both mentioned build types. -See :ref:`app_build_additions_build_types` and :ref:`modifying_build_types` for more information about this feature of the |NCS|. +See :ref:`app_build_additions_build_types` and :ref:`cmake_options` for more information. The application supports the following build types: @@ -374,11 +452,10 @@ The application supports the following build types: - File name - Supported board - Description - * - Debug + * - Debug (default) - :file:`prj.conf` - All from `Requirements`_ - - | Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs. - | Used by default if no build type is explicitly selected. + - Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs. * - Release - :file:`prj_release.conf` - All from `Requirements`_ @@ -391,11 +468,21 @@ Building and running .. include:: /includes/build_and_run.txt +.. include:: ../../../samples/matter/lock/README.rst + :start-after: matter_door_lock_sample_nrf70_firmware_patch_start + :end-before: matter_door_lock_sample_nrf70_firmware_patch_end + +For example: + + .. code-block:: console + + west build -b nrf5340dk_nrf5340_cpuapp -p -- -DSHIELD=nrf7002ek -DCONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE=y -Dmcuboot_CONFIG_UPDATEABLE_IMAGE_NUMBER=3 + Selecting a build type ====================== -Before you start testing the application, you can select one of the :ref:`matter_bridge_app_build_types`, depending on your building method. -See :ref:`modifying_build_types` for detailed steps how to select a build type. +Before you start testing the application, you can select one of the :ref:`matter_bridge_app_build_types`. +See :ref:`cmake_options` for information about how to select a build type. .. _matter_bridge_testing: @@ -458,6 +545,7 @@ After building the sample and programming it to your development kit, complete t * :ref:`peripheral_esp` #. Connect the development kit that is running the Bluetooth LE sample to the PC. + #. |connect_terminal_ANSI| #. Using the terminal emulator connected to the bridge, run the following :ref:`Matter CLI command ` to scan for available Bluetooth LE devices: .. code-block:: console @@ -496,6 +584,49 @@ After building the sample and programming it to your development kit, complete t .. parsed-literal:: :class: highlight + I: Connected: C7:44:0F:3E:BB:F0 (random) + ---------------------------------------------------------------------------------------- + | Bridged Bluetooth LE device authentication | + | | + | Insert pin code displayed by the Bluetooth LE peripheral device | + | to authenticate the pairing operation. | + | | + | To do that, use matter_bridge pincode shell command. | + ---------------------------------------------------------------------------------------- + + #. Write down the authentication pincode value from the Bluetooth LE bridged device terminal. + The terminal output is similar to the following one: + + .. parsed-literal:: + :class: highlight + + Passkey for FD:D6:53:EB:92:3A (random): 350501 + + In the above example output, the displayed pincode value is ``350501``. + It will be used in the next steps as **. + #. Insert the authentication pincode of the bridged device in the Matter bridge terminal. + To insert the pincode, run the following :ref:`Matter CLI command ` with ** replaced by the value read in the previous step: + + .. parsed-literal:: + :class: highlight + + uart:~$ matter_bridge pincode ** ** + + For example, if you want to add a new Bluetooth LE bridged device with index ``1`` and pincode ``350501``, use the following command: + + .. code-block:: console + + uart:~$ matter_bridge pincode 1 350501 + + The terminal output is similar to the following one: + + .. parsed-literal:: + :class: highlight + + I: Pairing completed: E3:9D:5E:51:AD:14 (random), bonded: 1 + + I: Security changed: level 4 + I: The GATT discovery completed I: Added device to dynamic endpoint 3 (index=0) I: Added device to dynamic endpoint 4 (index=1) I: Created 0x100 device type on the endpoint 3 diff --git a/applications/matter_bridge/overlay-bt_max_connections_app.conf b/applications/matter_bridge/overlay-bt_max_connections_app.conf index 87141a641f7..83de533d7cd 100644 --- a/applications/matter_bridge/overlay-bt_max_connections_app.conf +++ b/applications/matter_bridge/overlay-bt_max_connections_app.conf @@ -8,15 +8,15 @@ CONFIG_BT_MAX_CONN=20 # Set buffer sizes in a consistent way with the ones used by the network core. -CONFIG_BT_BUF_ACL_RX_SIZE=96 -CONFIG_BT_BUF_ACL_TX_SIZE=96 -CONFIG_BT_CTLR_DATA_LENGTH_MAX=96 +CONFIG_BT_BUF_ACL_RX_SIZE=84 +CONFIG_BT_BUF_ACL_TX_SIZE=84 # Set MTU size to fit in the single buffer and avoid fragmentation (BUF_SIZE = MTU_SIZE + 4 B of L2CAP header). -CONFIG_BT_L2CAP_TX_MTU=92 +CONFIG_BT_L2CAP_TX_MTU=80 # Set max number of bridged BLE devices, which is CONFIG_BT_MAX_CONN-1, as 1 connection is reserved for Matter. CONFIG_BRIDGE_MAX_BRIDGED_DEVICES_NUMBER=19 +CONFIG_BT_MAX_PAIRED=19 # Assume that every bridged device uses only 1 endpoint, however it can be increased if specific use case requires it. CONFIG_BRIDGE_MAX_DYNAMIC_ENDPOINTS_NUMBER=19 diff --git a/applications/matter_bridge/overlay-bt_max_connections_net.conf b/applications/matter_bridge/overlay-bt_max_connections_net.conf index 32b76399ffc..f4195e295ff 100644 --- a/applications/matter_bridge/overlay-bt_max_connections_net.conf +++ b/applications/matter_bridge/overlay-bt_max_connections_net.conf @@ -10,6 +10,6 @@ CONFIG_BT_MAX_CONN=20 # Decrease stack and buffer sizes to free some RAM and support 20 BLE connections CONFIG_MAIN_STACK_SIZE=512 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 -CONFIG_BT_BUF_ACL_RX_SIZE=96 -CONFIG_BT_BUF_ACL_TX_SIZE=96 -CONFIG_BT_CTLR_DATA_LENGTH_MAX=96 +CONFIG_BT_BUF_ACL_RX_SIZE=84 +CONFIG_BT_BUF_ACL_TX_SIZE=84 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=84 diff --git a/applications/matter_bridge/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/applications/matter_bridge/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000..995593ad0ee --- /dev/null +++ b/applications/matter_bridge/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,80 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xeee00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xef000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xeee00 +factory_data: + address: 0xf7000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xf8000 + size: 0x8000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xef000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xef000 + size: 0x40000 + device: MX25R64 + region: external_flash +nrf70_wifi_fw_mcuboot_pad: + address: 0x12F000 + size: 0x200 + device: MX25R64 + region: external_flash +nrf70_wifi_fw: + address: 0x12F200 + size: 0x20000 + device: MX25R64 + region: external_flash +mcuboot_primary_2: + orig_span: &id003 + - nrf70_wifi_fw_mcuboot_pad + - nrf70_wifi_fw + span: *id003 + address: 0x12F000 + size: 0x21000 + device: MX25R64 + region: external_flash +mcuboot_secondary_2: + address: 0x150000 + size: 0x21000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x171000 + size: 0x68F000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/samples/matter/light_bulb/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/applications/matter_bridge/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml similarity index 100% rename from samples/matter/light_bulb/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to applications/matter_bridge/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml diff --git a/applications/matter_bridge/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/applications/matter_bridge/pm_static_nrf7002dk_nrf5340_cpuapp.yml similarity index 100% rename from applications/matter_bridge/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to applications/matter_bridge/pm_static_nrf7002dk_nrf5340_cpuapp.yml diff --git a/samples/matter/light_bulb/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/applications/matter_bridge/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml similarity index 100% rename from samples/matter/light_bulb/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to applications/matter_bridge/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml diff --git a/applications/matter_bridge/prj.conf b/applications/matter_bridge/prj.conf index e5cc6125eaf..0fbddc5dd1b 100644 --- a/applications/matter_bridge/prj.conf +++ b/applications/matter_bridge/prj.conf @@ -28,6 +28,9 @@ CONFIG_MPU_STACK_GUARD=y CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_CHIP_LIB_SHELL=y +# Reduce assert verbosity to save flash space. +CONFIG_ASSERT_NO_FILE_INFO=y + # Disable NFC commissioning CONFIG_CHIP_NFC_COMMISSIONING=n diff --git a/applications/matter_bridge/sample.yaml b/applications/matter_bridge/sample.yaml index 896623595fa..d925325980d 100644 --- a/applications/matter_bridge/sample.yaml +++ b/applications/matter_bridge/sample.yaml @@ -5,23 +5,54 @@ tests: applications.matter_bridge.release: build_only: true extra_args: CONF_FILE=prj_release.conf + CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y integration_platforms: - nrf7002dk_nrf5340_cpuapp platform_allow: nrf7002dk_nrf5340_cpuapp applications.matter_bridge.debug: build_only: true + extra_args: CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y + integration_platforms: + - nrf7002dk_nrf5340_cpuapp + platform_allow: nrf7002dk_nrf5340_cpuapp + applications.matter_bridge.smp_dfu: + build_only: true + extra_args: CONFIG_CHIP_DFU_OVER_BT_SMP=y + CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y integration_platforms: - nrf7002dk_nrf5340_cpuapp platform_allow: nrf7002dk_nrf5340_cpuapp applications.matter_bridge.release.br_ble: build_only: true extra_args: CONF_FILE=prj_release.conf CONFIG_BRIDGED_DEVICE_BT=y + CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y integration_platforms: - nrf7002dk_nrf5340_cpuapp platform_allow: nrf7002dk_nrf5340_cpuapp applications.matter_bridge.smp_dfu.br_ble: build_only: true extra_args: CONFIG_CHIP_DFU_OVER_BT_SMP=y CONFIG_BRIDGED_DEVICE_BT=y + CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y + integration_platforms: + - nrf7002dk_nrf5340_cpuapp + platform_allow: nrf7002dk_nrf5340_cpuapp + applications.matter_bridge.nrf70ek: + build_only: true + extra_args: SHIELD=nrf7002ek CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE=y + mcuboot_CONFIG_UPDATEABLE_IMAGE_NUMBER=3 + integration_platforms: + - nrf5340dk_nrf5340_cpuapp + platform_allow: nrf5340dk_nrf5340_cpuapp + applications.matter_bridge.memory_profiling: + build_only: true + extra_args: CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE=n + CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE=y + CONFIG_CHIP_MEMORY_PROFILING=y integration_platforms: - nrf7002dk_nrf5340_cpuapp platform_allow: nrf7002dk_nrf5340_cpuapp diff --git a/applications/matter_bridge/src/app_task.cpp b/applications/matter_bridge/src/app_task.cpp index 7b5aa64f497..730aa9370ef 100644 --- a/applications/matter_bridge/src/app_task.cpp +++ b/applications/matter_bridge/src/app_task.cpp @@ -12,11 +12,11 @@ #include "simulated_bridged_device_factory.h" #endif /* CONFIG_BRIDGED_DEVICE_BT */ +#include "app/matter_init.h" +#include "app/task_executor.h" #include "board/board.h" #include "bridge/bridge_manager.h" #include "bridge/bridge_storage_manager.h" -#include "init/matter_init.h" -#include "tasks/task_executor.h" #ifdef CONFIG_BRIDGED_DEVICE_BT #include "bridge/ble_connectivity_manager.h" @@ -44,77 +44,82 @@ using namespace ::chip::DeviceLayer; namespace { #ifdef CONFIG_BRIDGED_DEVICE_BT -static bt_uuid *sUuidLbs = BT_UUID_LBS; -static bt_uuid *sUuidEs = BT_UUID_ESS; -static bt_uuid *sUuidServices[] = { sUuidLbs, sUuidEs }; +static const bt_uuid *sUuidLbs = BT_UUID_LBS; +static const bt_uuid *sUuidEs = BT_UUID_ESS; +static const bt_uuid *sUuidServices[] = { sUuidLbs, sUuidEs }; static constexpr uint8_t kUuidServicesNumber = ARRAY_SIZE(sUuidServices); -#endif /* CONFIG_BRIDGED_DEVICE_BT */ - -} /* namespace */ +/** + * @brief Blink rates for indication the BLE Connectivity Manager state. + * + */ +constexpr static uint32_t kPairingBlinkRate{ 100 }; +constexpr static uint32_t kScanningBlinkRate_ms{ 300 }; +constexpr static uint32_t kLostBlinkRate_ms{ 1000 }; -void AppTask::MatterEventHandler(const ChipDeviceEvent *event, intptr_t /* arg */) +void BLEStateChangeCallback(Nrf::BLEConnectivityManager::State state) { - bool isNetworkProvisioned = false; - - switch (event->Type) { - case DeviceEventType::kCHIPoBLEAdvertisingChange: - if (ConnectivityMgr().NumBLEConnections() != 0) { - GetBoard().UpdateDeviceState(DeviceState::DeviceConnectedBLE); - } + switch (state) { + case Nrf::BLEConnectivityManager::State::Connected: + Nrf::PostTask([] { Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Set(true); }); break; -#if defined(CONFIG_CHIP_WIFI) - case DeviceEventType::kWiFiConnectivityChange: - isNetworkProvisioned = - ConnectivityMgr().IsWiFiStationProvisioned() && ConnectivityMgr().IsWiFiStationEnabled(); -#if CONFIG_CHIP_OTA_REQUESTOR - if (event->WiFiConnectivityChange.Result == kConnectivity_Established) { - InitBasicOTARequestor(); - } -#endif /* CONFIG_CHIP_OTA_REQUESTOR */ -#endif - if (isNetworkProvisioned) { - GetBoard().UpdateDeviceState(DeviceState::DeviceProvisioned); - } else { - GetBoard().UpdateDeviceState(DeviceState::DeviceDisconnected); - } + case Nrf::BLEConnectivityManager::State::Scanning: + Nrf::PostTask([] { + Nrf::GetBoard() + .GetLED(Nrf::DeviceLeds::LED2) + .Blink(kScanningBlinkRate_ms, kScanningBlinkRate_ms); + }); break; - default: + case Nrf::BLEConnectivityManager::State::LostDevice: + Nrf::PostTask([] { + Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Blink(kLostBlinkRate_ms, kLostBlinkRate_ms); + }); break; + case Nrf::BLEConnectivityManager::State::Pairing: + Nrf::PostTask([] { + Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Blink(kPairingBlinkRate, kPairingBlinkRate); + }); + break; + default: + Nrf::PostTask([] { Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Set(false); }); } } +#endif /* CONFIG_BRIDGED_DEVICE_BT */ + +} /* namespace */ + CHIP_ERROR AppTask::RestoreBridgedDevices() { uint8_t count; - uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 }; + uint8_t indexes[Nrf::BridgeManager::kMaxBridgedDevices] = { 0 }; size_t indexesCount = 0; - if (!BridgeStorageManager::Instance().LoadBridgedDevicesCount(count)) { + if (!Nrf::BridgeStorageManager::Instance().LoadBridgedDevicesCount(count)) { LOG_INF("No bridged devices to load from the storage."); return CHIP_NO_ERROR; } - if (!BridgeStorageManager::Instance().LoadBridgedDevicesIndexes(indexes, BridgeManager::kMaxBridgedDevices, - indexesCount)) { + if (!Nrf::BridgeStorageManager::Instance().LoadBridgedDevicesIndexes( + indexes, Nrf::BridgeManager::kMaxBridgedDevices, indexesCount)) { return CHIP_NO_ERROR; } /* Load all devices based on the read count number. */ for (size_t i = 0; i < indexesCount; i++) { uint16_t endpointId; - char label[MatterBridgedDevice::kNodeLabelSize] = { 0 }; + char label[Nrf::MatterBridgedDevice::kNodeLabelSize] = { 0 }; size_t labelSize; uint16_t deviceType; - if (!BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, indexes[i])) { + if (!Nrf::BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, indexes[i])) { return CHIP_ERROR_NOT_FOUND; } /* Ignore an error, as node label is optional, so it may not be found. */ - BridgeStorageManager::Instance().LoadBridgedDeviceNodeLabel(label, sizeof(label), labelSize, - indexes[i]); + Nrf::BridgeStorageManager::Instance().LoadBridgedDeviceNodeLabel(label, sizeof(label), labelSize, + indexes[i]); - if (!BridgeStorageManager::Instance().LoadBridgedDeviceType(deviceType, indexes[i])) { + if (!Nrf::BridgeStorageManager::Instance().LoadBridgedDeviceType(deviceType, indexes[i])) { return CHIP_ERROR_NOT_FOUND; } @@ -123,7 +128,7 @@ CHIP_ERROR AppTask::RestoreBridgedDevices() #ifdef CONFIG_BRIDGED_DEVICE_BT bt_addr_le_t addr; - if (!BridgeStorageManager::Instance().LoadBtAddress(addr, indexes[i])) { + if (!Nrf::BridgeStorageManager::Instance().LoadBtAddress(addr, indexes[i])) { return CHIP_ERROR_NOT_FOUND; } @@ -139,34 +144,38 @@ CHIP_ERROR AppTask::RestoreBridgedDevices() CHIP_ERROR AppTask::Init() { /* Initialize Matter stack */ - ReturnErrorOnFailure(Nordic::Matter::PrepareServer( - MatterEventHandler, Nordic::Matter::InitData{ .mPostServerInitClbk = [] { + ReturnErrorOnFailure(Nrf::Matter::PrepareServer(Nrf::Matter::InitData{ .mPostServerInitClbk = [] { #ifdef CONFIG_BRIDGED_DEVICE_BT - /* Initialize BLE Connectivity Manager before the Bridge Manager, as it must be ready to recover - * devices loaded from persistent storage during the bridge init. */ - CHIP_ERROR bleInitError = - BLEConnectivityManager::Instance().Init(sUuidServices, kUuidServicesNumber); - if (bleInitError != CHIP_NO_ERROR) { - LOG_ERR("BLEConnectivityManager initialization failed"); - return bleInitError; - } + Nrf::BLEConnectivityManager::Instance().RegisterStateCallback(BLEStateChangeCallback); + /* Initialize BLE Connectivity Manager before the Bridge Manager, as it must be ready to recover + * devices loaded from persistent storage during the bridge init. */ + CHIP_ERROR bleInitError = + Nrf::BLEConnectivityManager::Instance().Init(sUuidServices, kUuidServicesNumber); + if (bleInitError != CHIP_NO_ERROR) { + LOG_ERR("BLEConnectivityManager initialization failed"); + return bleInitError; + } #endif - /* Initialize bridge manager */ - CHIP_ERROR bridgeMgrInitError = BridgeManager::Instance().Init(RestoreBridgedDevices); - if (bridgeMgrInitError != CHIP_NO_ERROR) { - LOG_ERR("BridgeManager initialization failed"); - return bridgeMgrInitError; - } - return CHIP_NO_ERROR; - } })); + /* Initialize bridge manager */ + CHIP_ERROR bridgeMgrInitError = Nrf::BridgeManager::Instance().Init(RestoreBridgedDevices); + if (bridgeMgrInitError != CHIP_NO_ERROR) { + LOG_ERR("BridgeManager initialization failed"); + return bridgeMgrInitError; + } + return CHIP_NO_ERROR; + } })); - if (!GetBoard().Init()) { + if (!Nrf::GetBoard().Init()) { LOG_ERR("User interface initialization failed."); return CHIP_ERROR_INCORRECT_STATE; } - return Nordic::Matter::StartServer(); + /* Register Matter event handler that controls the connectivity status LED based on the captured Matter network + * state. */ + ReturnErrorOnFailure(Nrf::Matter::RegisterEventHandler(Nrf::Board::DefaultMatterEventHandler, 0)); + + return Nrf::Matter::StartServer(); } CHIP_ERROR AppTask::StartApp() @@ -174,7 +183,7 @@ CHIP_ERROR AppTask::StartApp() ReturnErrorOnFailure(Init()); while (true) { - TaskExecutor::DispatchNextTask(); + Nrf::DispatchNextTask(); } return CHIP_NO_ERROR; diff --git a/applications/matter_bridge/src/app_task.h b/applications/matter_bridge/src/app_task.h index 7b63f8c0e62..bed25a1745e 100644 --- a/applications/matter_bridge/src/app_task.h +++ b/applications/matter_bridge/src/app_task.h @@ -21,6 +21,5 @@ class AppTask { private: CHIP_ERROR Init(); - static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t arg); static CHIP_ERROR RestoreBridgedDevices(); }; diff --git a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp index f176814603e..a00b5cdab6d 100644 --- a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp +++ b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.cpp @@ -12,6 +12,8 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); +using namespace Nrf; + namespace { /* Maps single Matter device type to corresponding BLE service. */ @@ -122,10 +124,11 @@ CHIP_ERROR AddMatterDevices(MatterBridgedDevice::DeviceType deviceTypes[], uint8 uint16_t endpointIds[] = nullptr) { VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT, LOG_ERR("No valid data provider!")); + chip::Platform::UniquePtr providerPtr(provider); VerifyOrReturnError(count <= BridgeManager::kMaxBridgedDevicesPerProvider, CHIP_ERROR_BUFFER_TOO_SMALL, LOG_ERR("Trying to add too many endpoints for single provider device.")); - CHIP_ERROR err; + CHIP_ERROR err = CHIP_NO_ERROR; MatterBridgedDevice *newBridgedDevices[BridgeManager::kMaxBridgedDevicesPerProvider]; uint8_t deviceIndexes[BridgeManager::kMaxBridgedDevicesPerProvider]; @@ -135,36 +138,50 @@ CHIP_ERROR AddMatterDevices(MatterBridgedDevice::DeviceType deviceTypes[], uint8 forceIndexesAndEndpoints = true; } - for (uint8_t i = 0; i < count; i++) { - newBridgedDevices[i] = - BleBridgedDeviceFactory::GetBridgedDeviceFactory().Create(deviceTypes[i], nodeLabel); + uint8_t addedDevicesCount = 0; + for (; addedDevicesCount < count; addedDevicesCount++) { + newBridgedDevices[addedDevicesCount] = BleBridgedDeviceFactory::GetBridgedDeviceFactory().Create( + deviceTypes[addedDevicesCount], nodeLabel); - if (!newBridgedDevices[i]) { + if (!newBridgedDevices[addedDevicesCount]) { LOG_ERR("Cannot allocate Matter device of given type"); - return CHIP_ERROR_NO_MEMORY; + err = CHIP_ERROR_NO_MEMORY; + break; } if (forceIndexesAndEndpoints) { - deviceIndexes[i] = indexes[i]; + deviceIndexes[addedDevicesCount] = indexes[addedDevicesCount]; + } + } + + /* Not all requested devices were created successfully, delete all previously created objects and return. */ + if (err != CHIP_NO_ERROR) { + for (uint8_t i = 0; i < addedDevicesCount; i++) { + chip::Platform::Delete(newBridgedDevices[i]); } + return err; } if (forceIndexesAndEndpoints) { - err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, provider, count, deviceIndexes, - endpointIds); + err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, providerPtr.get(), count, + deviceIndexes, endpointIds); } else { - err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, provider, count, deviceIndexes); + err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, providerPtr.get(), count, + deviceIndexes); } if (err == CHIP_NO_ERROR) { for (uint8_t i = 0; i < count; i++) { - err = StoreDevice(newBridgedDevices[i], provider, deviceIndexes[i]); + err = StoreDevice(newBridgedDevices[i], providerPtr.get(), deviceIndexes[i]); if (err != CHIP_NO_ERROR) { break; } } } + /* The ownership was transferred unconditionally to the BridgeManager, release the pointer. */ + providerPtr.release(); + if (err != CHIP_NO_ERROR) { LOG_ERR("Adding Matter bridged device failed: %s", ErrorStr(err)); } else { @@ -184,36 +201,29 @@ struct BluetoothConnectionContext { bt_addr_le_t address; }; -void BluetoothDeviceConnected(bool discoverySucceeded, void *context) +CHIP_ERROR BluetoothDeviceConnected(bool success, void *context) { if (!context) { - return; + return CHIP_ERROR_INVALID_ARGUMENT; } BluetoothConnectionContext *ctx = reinterpret_cast(context); - VerifyOrExit(discoverySucceeded, ); - - /* Schedule adding device to main thread to avoid overflowing the BT stack. */ - VerifyOrExit(chip::DeviceLayer::PlatformMgr().ScheduleWork( - [](intptr_t context) { - BluetoothConnectionContext *ctx = - reinterpret_cast(context); - chip::Optional indexes[BridgeManager::kMaxBridgedDevicesPerProvider]; - chip::Optional endpointIds[BridgeManager::kMaxBridgedDevicesPerProvider]; - if (CHIP_NO_ERROR != AddMatterDevices(ctx->deviceTypes, ctx->count, ctx->nodeLabel, - ctx->provider)) { - BLEConnectivityManager::Instance().RemoveBLEProvider(ctx->address); - chip::Platform::Delete(ctx->provider); - } - chip::Platform::Delete(ctx); - }, - reinterpret_cast(ctx)) == CHIP_NO_ERROR, ); - return; + if (!success) { + chip::Platform::Delete(ctx->provider); + chip::Platform::Delete(ctx); + return CHIP_ERROR_INTERNAL; + } -exit: - BLEConnectivityManager::Instance().RemoveBLEProvider(ctx->address); + /* Discovery was successful, try to bridge connected BLE device with the Matter counterpart. */ + chip::Optional indexes[BridgeManager::kMaxBridgedDevicesPerProvider]; + chip::Optional endpointIds[BridgeManager::kMaxBridgedDevicesPerProvider]; + /* AddMatterDevices takes the ownership of the passed provider object and will + delete it in case the BridgeManager fails to accept this object. */ + CHIP_ERROR err = AddMatterDevices(ctx->deviceTypes, ctx->count, ctx->nodeLabel, ctx->provider); chip::Platform::Delete(ctx); + + return err; } } // namespace @@ -281,14 +291,18 @@ BleBridgedDeviceFactory::BleDataProviderFactory &BleBridgedDeviceFactory::GetDat { static BleDataProviderFactory sDeviceDataProvider { -#if defined(CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE) && (defined(CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE) || defined(CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE)) +#if defined(CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE) && (defined(CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE) || \ + defined(CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE)) { ServiceUuid::LedButtonService, - [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, + [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { + return chip::Platform::New(updateClb, commandClb); + } }, #endif #if defined(CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE) && defined(CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE) - { ServiceUuid::EnvironmentalSensorService, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { - return chip::Platform::New(updateClb, commandClb); - } }, + { ServiceUuid::EnvironmentalSensorService, + [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { + return chip::Platform::New(updateClb, commandClb); + } }, #endif }; return sDeviceDataProvider; @@ -313,8 +327,8 @@ CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(int deviceType, bt_addr_le_t bt err = MatterDeviceTypeToBleService(static_cast(deviceType), providerType); VerifyOrExit(err == CHIP_NO_ERROR, ); - provider = static_cast( - BleBridgedDeviceFactory::GetDataProviderFactory().Create(providerType, BridgeManager::HandleUpdate, BridgeManager::HandleCommand)); + provider = static_cast(BleBridgedDeviceFactory::GetDataProviderFactory().Create( + providerType, BridgeManager::HandleUpdate, BridgeManager::HandleCommand)); if (!provider) { return CHIP_ERROR_NO_MEMORY; } @@ -325,24 +339,36 @@ CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(int deviceType, bt_addr_le_t bt /* Confirm that the first connection was done and this will be only the device recovery. */ provider->ConfirmInitialConnection(); provider->InitializeBridgedDevice(btAddress, nullptr, nullptr); - BLEConnectivityManager::Instance().Recover(provider); err = AddMatterDevices(reinterpret_cast(&deviceType), 1, nodeLabel, provider, &index, &endpointId); -exit: if (err != CHIP_NO_ERROR) { - BLEConnectivityManager::Instance().RemoveBLEProvider(btAddress); + return err; + } + + BLEConnectivityManager::Instance().Recover(provider); + +exit: + if (err != CHIP_NO_ERROR) { chip::Platform::Delete(provider); } return err; } -CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel) +CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel, + BLEConnectivityManager::ConnectionSecurityRequest *request) { - BLEBridgedDeviceProvider *provider = - static_cast(BleBridgedDeviceFactory::GetDataProviderFactory().Create( - static_cast(uuid), BridgeManager::HandleUpdate, BridgeManager::HandleCommand)); + /* Check if there is already existing provider for given address. + * In case it is, the provider was either connected or recovered before. + */ + BLEBridgedDeviceProvider *provider = BLEConnectivityManager::Instance().FindBLEProvider(btAddress); + if (provider) { + return CHIP_ERROR_INCORRECT_STATE; + } + + provider = static_cast(BleBridgedDeviceFactory::GetDataProviderFactory().Create( + static_cast(uuid), BridgeManager::HandleUpdate, BridgeManager::HandleCommand)); if (!provider) { return CHIP_ERROR_NO_MEMORY; } @@ -375,16 +401,14 @@ CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btA contextPtr->address = btAddress; provider->InitializeBridgedDevice(btAddress, BluetoothDeviceConnected, contextPtr.get()); - err = BLEConnectivityManager::Instance().Connect(provider); + err = BLEConnectivityManager::Instance().Connect(provider, request); if (err == CHIP_NO_ERROR) { contextPtr.release(); } exit: - if (err != CHIP_NO_ERROR) { - BLEConnectivityManager::Instance().RemoveBLEProvider(btAddress); chip::Platform::Delete(provider); } diff --git a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h index 67c1194da98..6fe7fe5a896 100644 --- a/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h +++ b/applications/matter_bridge/src/ble_providers/ble_bridged_device_factory.h @@ -46,11 +46,11 @@ namespace BleBridgedDeviceFactory /* The values were assigned based on BT_UUID_16(uuid)->val of a BT services. */ enum ServiceUuid : uint16_t { LedButtonService = 0xbcd1, EnvironmentalSensorService = 0x181a }; -using UpdateAttributeCallback = BridgedDeviceDataProvider::UpdateAttributeCallback; -using InvokeCommandCallback = BridgedDeviceDataProvider::InvokeCommandCallback; +using UpdateAttributeCallback = Nrf::BridgedDeviceDataProvider::UpdateAttributeCallback; +using InvokeCommandCallback = Nrf::BridgedDeviceDataProvider::InvokeCommandCallback; using DeviceType = uint16_t; -using BridgedDeviceFactory = DeviceFactory; -using BleDataProviderFactory = DeviceFactory; +using BridgedDeviceFactory = Nrf::DeviceFactory; +using BleDataProviderFactory = Nrf::DeviceFactory; BridgedDeviceFactory &GetBridgedDeviceFactory(); BleDataProviderFactory &GetDataProviderFactory(); @@ -76,10 +76,12 @@ CHIP_ERROR CreateDevice(int deviceType, bt_addr_le_t btAddress, const char *node * @param uuid the Bluetooth LE service UUID of a bridged device provider that will be paired with bridged device * @param btAddress the Bluetooth LE address of a device to be bridged with created Matter device * @param nodeLabel node label of a Matter device to be created + * @param request address of connection request object for handling additional security information requiered by the connection. + * Can be nullptr, if connection does not use security. * @return CHIP_NO_ERROR on success * @return other error code on failure */ -CHIP_ERROR CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel); +CHIP_ERROR CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel, Nrf::BLEConnectivityManager::ConnectionSecurityRequest * request = nullptr); /** * @brief Remove bridged device. diff --git a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.cpp b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.cpp index 51eaee1d6ed..e089362badd 100644 --- a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.cpp +++ b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.cpp @@ -16,11 +16,12 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; -static bt_uuid *sServiceUuid = BT_UUID_ESS; -static bt_uuid *sUuidTemperature = BT_UUID_TEMPERATURE; -static bt_uuid *sUuidHumidity = BT_UUID_HUMIDITY; -static bt_uuid *sUuidCcc = BT_UUID_GATT_CCC; +static const bt_uuid *sServiceUuid = BT_UUID_ESS; +static const bt_uuid *sUuidTemperature = BT_UUID_TEMPERATURE; +static const bt_uuid *sUuidHumidity = BT_UUID_HUMIDITY; +static const bt_uuid *sUuidCcc = BT_UUID_GATT_CCC; bt_gatt_read_params BleEnvironmentalDataProvider::sHumidityReadParams{}; @@ -30,7 +31,7 @@ BleEnvironmentalDataProvider *GetProvider(bt_conn *conn) BLEConnectivityManager::Instance().FindBLEProvider(*bt_conn_get_dst(conn))); } -bt_uuid *BleEnvironmentalDataProvider::GetServiceUuid() +const bt_uuid *BleEnvironmentalDataProvider::GetServiceUuid() { return sServiceUuid; } diff --git a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h index f121e40a5ba..edc4d28655a 100644 --- a/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h +++ b/applications/matter_bridge/src/ble_providers/ble_environmental_data_provider.h @@ -10,16 +10,16 @@ #include "ble_connectivity_manager.h" #include "bridged_device_data_provider.h" -class BleEnvironmentalDataProvider : public BLEBridgedDeviceProvider { +class BleEnvironmentalDataProvider : public Nrf::BLEBridgedDeviceProvider { public: - explicit BleEnvironmentalDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BLEBridgedDeviceProvider(updateCallback, commandCallback) {} + explicit BleEnvironmentalDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BLEBridgedDeviceProvider(updateCallback, commandCallback) {} ~BleEnvironmentalDataProvider() { Unsubscribe(); } void Init() override; void NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) override; CHIP_ERROR UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override; - bt_uuid *GetServiceUuid() override; + const bt_uuid *GetServiceUuid() override; int ParseDiscoveredData(bt_gatt_dm *discoveredData) override; private: diff --git a/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.cpp b/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.cpp index 152d29a9204..38954ecbf96 100644 --- a/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.cpp +++ b/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.cpp @@ -20,30 +20,26 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; -static bt_uuid *sServiceUuid = BT_UUID_LBS; -static bt_uuid *sUuidLED = BT_UUID_LBS_LED; -static bt_uuid *sUuidButton = BT_UUID_LBS_BUTTON; -static bt_uuid *sUuidCcc = BT_UUID_GATT_CCC; +static const bt_uuid *sServiceUuid = BT_UUID_LBS; +static const bt_uuid *sUuidLED = BT_UUID_LBS_LED; +static const bt_uuid *sUuidButton = BT_UUID_LBS_BUTTON; +static const bt_uuid *sUuidCcc = BT_UUID_GATT_CCC; #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE -void ProcessCommand(CommandId aCommandId, const EmberBindingTableEntry &aBinding, OperationalDeviceProxy *aDevice, void *aContext) +void ProcessCommand(const EmberBindingTableEntry &aBinding, OperationalDeviceProxy *aDevice, Nrf::Matter::BindingHandler::BindingData &aData) { CHIP_ERROR ret = CHIP_NO_ERROR; - BindingHandler::BindingData *data = reinterpret_cast(aContext); - auto onSuccess = [dataRef = data](const ConcreteCommandPath &commandPath, const StatusIB &status, const auto &dataResponse) { - LOG_DBG("Binding command applied successfully!"); + auto onSuccess = [dataRef = Platform::New(aData)]( + const ConcreteCommandPath &commandPath, const StatusIB &status, + const auto &dataResponse) { Matter::BindingHandler::OnInvokeCommandSucces(dataRef); }; - /* If session was recovered and communication works, reset flag to the initial state. */ - if (dataRef->CaseSessionRecovered) { - dataRef->CaseSessionRecovered = false; - } - }; - - auto onFailure = [dataRef = *data](CHIP_ERROR aError) mutable { - BindingHandler::OnInvokeCommandFailure(dataRef, aError); - }; + auto onFailure = + [dataRef = Platform::New(aData)](CHIP_ERROR aError) mutable { + Matter::BindingHandler::OnInvokeCommandFailure(dataRef, aError); + }; if (aDevice) { /* We are validating connection is ready once here instead of multiple times in each case statement @@ -175,13 +171,13 @@ CHIP_ERROR BleLBSDataProvider::UpdateState(chip::ClusterId clusterId, chip::Attr return CHIP_NO_ERROR; } default: - return CHIP_ERROR_INVALID_ARGUMENT; + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } return CHIP_NO_ERROR; } -bt_uuid *BleLBSDataProvider::GetServiceUuid() +const bt_uuid *BleLBSDataProvider::GetServiceUuid() { return sServiceUuid; } diff --git a/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.h b/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.h index 93dc795eac8..8ba37b92985 100644 --- a/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.h +++ b/applications/matter_bridge/src/ble_providers/ble_lbs_data_provider.h @@ -12,7 +12,7 @@ #include -class BleLBSDataProvider : public BLEBridgedDeviceProvider { +class BleLBSDataProvider : public Nrf::BLEBridgedDeviceProvider { public: explicit BleLBSDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BLEBridgedDeviceProvider(updateCallback, commandCallback) @@ -33,7 +33,7 @@ class BleLBSDataProvider : public BLEBridgedDeviceProvider { static uint8_t GattNotifyCallback(bt_conn *conn, bt_gatt_subscribe_params *params, const void *data, uint16_t length); - bt_uuid *GetServiceUuid() override; + const bt_uuid *GetServiceUuid() override; int ParseDiscoveredData(bt_gatt_dm *discoveredData) override; private: diff --git a/applications/matter_bridge/src/bridge.matter b/applications/matter_bridge/src/bridge.matter index aba00dfd019..6535158740b 100644 --- a/applications/matter_bridge/src/bridge.matter +++ b/applications/matter_bridge/src/bridge.matter @@ -1,6 +1,54 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +client cluster Identify = 3 { + enum EffectIdentifierEnum : enum8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : enum8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : enum8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + int16u identifyTime = 0; + } + + request struct TriggerEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ server cluster Identify = 3 { enum EffectIdentifierEnum : enum8 { @@ -229,9 +277,23 @@ server cluster OnOff = 6 { readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + request struct OffWithEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + int8u effectVariant = 1; + } + + request struct OnWithTimedOffRequest { + OnOffControlBitmap onOffControl = 0; + int16u onTime = 1; + int16u offWaitTime = 2; + } + command Off(): DefaultSuccess = 0; command On(): DefaultSuccess = 1; command Toggle(): DefaultSuccess = 2; + command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64; + command OnWithRecallGlobalScene(): DefaultSuccess = 65; + command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66; } /** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ @@ -1082,6 +1144,58 @@ server cluster BridgedDeviceBasicInformation = 57 { readonly attribute int16u clusterRevision = 65533; } +/** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. +Two types of switch devices are supported: latching switch (e.g. rocker switch) and momentary switch (e.g. push button), distinguished with their feature flags. +Interactions with the switch device are exposed as attributes (for the latching switch) and as events (for both types of switches). An interested party MAY subscribe to these attributes/events and thus be informed of the interactions, and can perform actions based on this, for example by sending commands to perform an action such as controlling a light or a window shade. */ +server cluster Switch = 59 { + bitmap Feature : bitmap32 { + kLatchingSwitch = 0x1; + kMomentarySwitch = 0x2; + kMomentarySwitchRelease = 0x4; + kMomentarySwitchLongPress = 0x8; + kMomentarySwitchMultiPress = 0x10; + } + + info event SwitchLatched = 0 { + int8u newPosition = 0; + } + + info event InitialPress = 1 { + int8u newPosition = 0; + } + + info event LongPress = 2 { + int8u newPosition = 0; + } + + info event ShortRelease = 3 { + int8u previousPosition = 0; + } + + info event LongRelease = 4 { + int8u previousPosition = 0; + } + + info event MultiPressOngoing = 5 { + int8u newPosition = 0; + int8u currentNumberOfPressesCounted = 1; + } + + info event MultiPressComplete = 6 { + int8u previousPosition = 0; + int8u totalNumberOfPressesCounted = 1; + } + + readonly attribute int8u numberOfPositions = 0; + readonly attribute int8u currentPosition = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** Commands to trigger a Node to allow a new Administrator to commission it. */ server cluster AdministratorCommissioning = 60 { enum CommissioningWindowStatusEnum : enum8 { @@ -1577,7 +1691,7 @@ endpoint 1 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 4; handle command Identify; } @@ -1598,6 +1712,7 @@ endpoint 1 { endpoint 2 { device type ma_onofflight = 256, version 2; + binding cluster Identify; binding cluster OnOff; server cluster Identify { @@ -1651,6 +1766,9 @@ endpoint 2 { handle command Off; handle command On; handle command Toggle; + handle command OffWithEffect; + handle command OnWithRecallGlobalScene; + handle command OnWithTimedOff; } server cluster Descriptor { @@ -1699,6 +1817,18 @@ endpoint 2 { ram attribute clusterRevision default = 2; } + server cluster Switch { + emits event InitialPress; + ram attribute numberOfPositions default = 2; + ram attribute currentPosition; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + } + server cluster TemperatureMeasurement { ram attribute measuredValue; ram attribute minMeasuredValue default = 0x8000; diff --git a/applications/matter_bridge/src/bridge.zap b/applications/matter_bridge/src/bridge.zap index 6f6f353282f..ca9930d7db8 100644 --- a/applications/matter_bridge/src/bridge.zap +++ b/applications/matter_bridge/src/bridge.zap @@ -882,7 +882,7 @@ "code": 2, "mfgCode": null, "side": "server", - "type": "OTAUpdateStateEnum", + "type": "UpdateStateEnum", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -1109,7 +1109,7 @@ "code": 2, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationType", + "type": "RegulatoryLocationTypeEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -1125,7 +1125,7 @@ "code": 3, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationType", + "type": "RegulatoryLocationTypeEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -1401,7 +1401,7 @@ "code": 5, "mfgCode": null, "side": "server", - "type": "NetworkCommissioningStatus", + "type": "NetworkCommissioningStatusEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -2165,7 +2165,7 @@ "code": 2, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "vendor_id", "included": 1, "storageOption": "External", "singleton": 0, @@ -2814,7 +2814,7 @@ "code": 1, "mfgCode": null, "side": "server", - "type": "enum8", + "type": "IdentifyTypeEnum", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -2915,7 +2915,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3122,6 +3122,58 @@ "deviceTypeCode": 256, "deviceTypeProfileId": 259, "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Identify", "code": 3, @@ -3169,7 +3221,7 @@ "code": 1, "mfgCode": null, "side": "server", - "type": "enum8", + "type": "IdentifyTypeEnum", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -3373,7 +3425,7 @@ "code": 0, "mfgCode": null, "side": "server", - "type": "bitmap8", + "type": "NameSupportBitmap", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -3513,6 +3565,30 @@ "source": "client", "isIncoming": 0, "isEnabled": 1 + }, + { + "name": "OffWithEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "OnWithRecallGlobalScene", + "code": 65, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "OnWithTimedOff", + "code": 66, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 } ], "attributes": [ @@ -3581,6 +3657,30 @@ "source": "client", "isIncoming": 1, "isEnabled": 1 + }, + { + "name": "OffWithEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OnWithRecallGlobalScene", + "code": 65, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OnWithTimedOff", + "code": 66, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 } ], "attributes": [ @@ -3653,7 +3753,7 @@ "code": 16387, "mfgCode": null, "side": "server", - "type": "OnOffStartUpOnOff", + "type": "StartUpOnOffEnum", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -4384,6 +4484,153 @@ } ] }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "NumberOfPositions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentPosition", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "InitialPress", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "Temperature Measurement", "code": 1026, diff --git a/applications/matter_bridge/src/bridge_shell.cpp b/applications/matter_bridge/src/bridge_shell.cpp index 01e1aaf4b10..f3009210e63 100644 --- a/applications/matter_bridge/src/bridge_shell.cpp +++ b/applications/matter_bridge/src/bridge_shell.cpp @@ -15,6 +15,34 @@ #include +#if defined(CONFIG_BRIDGED_DEVICE_BT) && defined(CONFIG_BT_SMP) +static void BluetoothConnectionSecurityRequest(void *context) +{ + if (!context) { + return; + } + + const struct shell *shell = reinterpret_cast(context); + + shell_fprintf(shell, SHELL_INFO, + "----------------------------------------------------------------------------------------\n"); + shell_fprintf(shell, SHELL_INFO, + "| Bridged Bluetooth LE device authentication |\n"); + shell_fprintf(shell, SHELL_INFO, + "| |\n"); + shell_fprintf(shell, SHELL_INFO, + "| Insert pin code displayed by the Bluetooth LE peripheral device |\n"); + shell_fprintf(shell, SHELL_INFO, + "| to authenticate the pairing operation. |\n"); + shell_fprintf(shell, SHELL_INFO, + "| |\n"); + shell_fprintf(shell, SHELL_INFO, + "| To do that, use matter_bridge pincode shell command. |\n"); + shell_fprintf(shell, SHELL_INFO, + "----------------------------------------------------------------------------------------\n"); +} +#endif /* CONFIG_BRIDGED_DEVICE_BT && CONFIG_BT_SMP */ + static int AddBridgedDeviceHandler(const struct shell *shell, size_t argc, char **argv) { char *nodeLabel = nullptr; @@ -28,18 +56,26 @@ static int AddBridgedDeviceHandler(const struct shell *shell, size_t argc, char } bt_addr_le_t address; - if (BLEConnectivityManager::Instance().GetScannedDeviceAddress(&address, bleDeviceIndex) != CHIP_NO_ERROR) { + if (Nrf::BLEConnectivityManager::Instance().GetScannedDeviceAddress(&address, bleDeviceIndex) != + CHIP_NO_ERROR) { shell_fprintf(shell, SHELL_ERROR, "Invalid Bluetooth LE device index.\n"); } else { shell_fprintf(shell, SHELL_ERROR, "Found device address\n"); } uint16_t uuid; - if (BLEConnectivityManager::Instance().GetScannedDeviceUuid(uuid, bleDeviceIndex) != CHIP_NO_ERROR) { + if (Nrf::BLEConnectivityManager::Instance().GetScannedDeviceUuid(uuid, bleDeviceIndex) != CHIP_NO_ERROR) { shell_fprintf(shell, SHELL_ERROR, "Invalid Bluetooth LE device index.\n"); } +#ifdef CONFIG_BT_SMP + Nrf::BLEConnectivityManager::ConnectionSecurityRequest request; + request.mCallback = BluetoothConnectionSecurityRequest; + request.mContext = const_cast(shell); + result = BleBridgedDeviceFactory::CreateDevice(uuid, address, nodeLabel, &request); +#else result = BleBridgedDeviceFactory::CreateDevice(uuid, address, nodeLabel); +#endif /* CONFIG_BT_SMP */ #elif defined(CONFIG_BRIDGED_DEVICE_SIMULATED) int deviceType = strtoul(argv[1], NULL, 0); @@ -57,6 +93,8 @@ static int AddBridgedDeviceHandler(const struct shell *shell, size_t argc, char if (result == CHIP_NO_ERROR) { shell_fprintf(shell, SHELL_INFO, "Done\n"); + } else if (result == CHIP_ERROR_INCORRECT_STATE) { + shell_fprintf(shell, SHELL_INFO, "Device is already added\n"); } else { shell_fprintf(shell, SHELL_ERROR, "Device add failed\n"); } @@ -86,13 +124,13 @@ static int RemoveBridgedDeviceHandler(const struct shell *shell, size_t argc, ch #ifdef CONFIG_BRIDGED_DEVICE_SIMULATED_ONOFF_SHELL static int SimulatedBridgedDeviceOnOffWriteHandler(const struct shell *shell, size_t argc, char **argv) { - using DeviceType = MatterBridgedDevice::DeviceType; + using DeviceType = Nrf::MatterBridgedDevice::DeviceType; const char *command = argv[0]; uint8_t value = strtoul(argv[1], nullptr, 0); chip::EndpointId endpointId = strtoul(argv[2], nullptr, 0); uint16_t deviceType{}; - auto *provider = BridgeManager().Instance().GetProvider(endpointId, deviceType); + auto *provider = Nrf::BridgeManager().Instance().GetProvider(endpointId, deviceType); if (provider) { if ((0 == strcmp(command, "onoff") && deviceType != DeviceType::OnOffLight)) { @@ -118,13 +156,13 @@ static int SimulatedBridgedDeviceOnOffWriteHandler(const struct shell *shell, si #if defined(CONFIG_BRIDGED_DEVICE_SIMULATED) && defined(CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE) static int SimulatedBridgedDeviceOnOffLightSwitchWriteHandler(const struct shell *shell, size_t argc, char **argv) { - using DeviceType = MatterBridgedDevice::DeviceType; + using DeviceType = Nrf::MatterBridgedDevice::DeviceType; const char *command = argv[0]; uint8_t value = strtoul(argv[1], nullptr, 0); chip::EndpointId endpointId = strtoul(argv[2], nullptr, 0); - DeviceType deviceType{}; - auto *provider = BridgeManager().Instance().GetProvider(endpointId, deviceType); + uint16_t deviceType{}; + auto *provider = Nrf::BridgeManager().Instance().GetProvider(endpointId, deviceType); if (provider) { if ((0 == strcmp(command, "onoff_switch") && deviceType != DeviceType::OnOffLightSwitch)) { @@ -148,9 +186,9 @@ static int SimulatedBridgedDeviceOnOffLightSwitchWriteHandler(const struct shell #endif #ifdef CONFIG_BRIDGED_DEVICE_BT -static void BluetoothScanResult(BLEConnectivityManager::ScannedDevice *devices, uint8_t count, void *context) +static void BluetoothScanResult(Nrf::BLEConnectivityManager::ScanResult &result, void *context) { - if (!devices || !context) { + if (!result.mDevices || !context) { return; } @@ -160,19 +198,40 @@ static void BluetoothScanResult(BLEConnectivityManager::ScannedDevice *devices, shell_fprintf(shell, SHELL_INFO, "---------------------------------------------------------------------\n"); shell_fprintf(shell, SHELL_INFO, "| Index | Address | UUID \n"); shell_fprintf(shell, SHELL_INFO, "---------------------------------------------------------------------\n"); - for (int i = 0; i < count; i++) { + for (int i = 0; i < result.mCount; i++) { shell_fprintf(shell, SHELL_INFO, "| %d | %02x:%02x:%02x:%02x:%02x:%02x | 0x%04x (%s)\n", i, - devices[i].mAddr.a.val[5], devices[i].mAddr.a.val[4], devices[i].mAddr.a.val[3], - devices[i].mAddr.a.val[2], devices[i].mAddr.a.val[1], devices[i].mAddr.a.val[0], - devices[i].mUuid, BleBridgedDeviceFactory::GetUuidString(devices[i].mUuid)); + result.mDevices[i].mAddr.a.val[5], result.mDevices[i].mAddr.a.val[4], + result.mDevices[i].mAddr.a.val[3], result.mDevices[i].mAddr.a.val[2], + result.mDevices[i].mAddr.a.val[1], result.mDevices[i].mAddr.a.val[0], + result.mDevices[i].mUuid, + BleBridgedDeviceFactory::GetUuidString(result.mDevices[i].mUuid)); } } +#ifdef CONFIG_BT_SMP +static int InsertBridgedDevicePincodeHandler(const struct shell *shell, size_t argc, char **argv) +{ + int bleDeviceIndex = strtoul(argv[1], NULL, 0); + unsigned int pincode = strtoul(argv[2], NULL, 10); + + bt_addr_le_t address; + if (Nrf::BLEConnectivityManager::Instance().GetScannedDeviceAddress(&address, bleDeviceIndex) != + CHIP_NO_ERROR) { + shell_fprintf(shell, SHELL_ERROR, "Invalid Bluetooth LE device index.\n"); + } else { + shell_fprintf(shell, SHELL_ERROR, "Found device address\n"); + } + + Nrf::BLEConnectivityManager::Instance().SetPincode(address, pincode); + return 0; +} +#endif /* CONFIG_BT_SMP */ + static int ScanBridgedDeviceHandler(const struct shell *shell, size_t argc, char **argv) { - shell_fprintf(shell, SHELL_INFO, "Scanning for 10 s ...\n"); + shell_fprintf(shell, SHELL_INFO, "Scanning for %d s ...\n", CONFIG_BRIDGE_BT_SCAN_TIMEOUT_MS / 1000); - BLEConnectivityManager::Instance().Scan(BluetoothScanResult, const_cast(shell)); + Nrf::BLEConnectivityManager::Instance().Scan(BluetoothScanResult, const_cast(shell)); return 0; } @@ -225,6 +284,14 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Scan for Bluetooth LE devices to bridge. \n" "Usage: scan\n", ScanBridgedDeviceHandler, 1, 0), +#ifdef CONFIG_BT_SMP + SHELL_CMD_ARG(pincode, NULL, + "Insert pincode for Bluetooth LE device pairing. \n" + "Usage: pincode \n" + "* ble_device_index - the Bluetooth LE device's index on the list returned by the scan command\n" + "* pincode - is a pin required for Bluetooth LE pairing authentication\n", + InsertBridgedDevicePincodeHandler, 3, 0), +#endif /* CONFIG_BT_SMP */ #endif /* CONFIG_BRIDGED_DEVICE_BT */ SHELL_SUBCMD_SET_END); diff --git a/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp b/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp index 67cdf65b500..73699494c78 100644 --- a/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp +++ b/applications/matter_bridge/src/bridged_device_types/generic_switch.cpp @@ -9,6 +9,9 @@ #include #include +#include +// #include +#include LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); @@ -21,18 +24,21 @@ IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchAttr) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::Switch::Attributes::NumberOfPositions::Id, INT8U, 1, 0), DECLARE_DYNAMIC_ATTRIBUTE(Clusters::Switch::Attributes::CurrentPosition::Id, INT8U, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::Switch::Attributes::FeatureMap::Id, BITMAP32, 4, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(genericSwitchClusters) DECLARE_DYNAMIC_CLUSTER(Clusters::Switch::Id, switchAttr, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER(Clusters::Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), sIdentifyIncomingCommands, - nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, + ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), + sIdentifyIncomingCommands, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(bridgedGenericSwitchEndpoint, genericSwitchClusters); @@ -107,6 +113,13 @@ CHIP_ERROR GenericSwitchDevice::HandleAttributeChange(chip::ClusterId clusterId, case Clusters::Switch::Attributes::CurrentPosition::Id: { err = CopyAttribute(data, dataSize, &mCurrentPosition, sizeof(mCurrentPosition)); VerifyOrReturnError(err == CHIP_NO_ERROR, err); + + /* The device supports only two positions, so non-zero means the switch was pressed. */ + if (mCurrentPosition) { + Clusters::Switch::Attributes::CurrentPosition::Set(mEndpointId, mCurrentPosition); + Clusters::SwitchServer::Instance().OnInitialPress(mEndpointId, mCurrentPosition); + } + break; } default: diff --git a/applications/matter_bridge/src/bridged_device_types/generic_switch.h b/applications/matter_bridge/src/bridged_device_types/generic_switch.h index 0fc77daf126..4b6fbef3136 100644 --- a/applications/matter_bridge/src/bridged_device_types/generic_switch.h +++ b/applications/matter_bridge/src/bridged_device_types/generic_switch.h @@ -8,13 +8,13 @@ #include "matter_bridged_device.h" -class GenericSwitchDevice : public MatterBridgedDevice { +class GenericSwitchDevice : public Nrf::MatterBridgedDevice { public: GenericSwitchDevice(const char *nodeLabel); uint16_t GetDeviceType() const override { - return MatterBridgedDevice::DeviceType::GenericSwitch; + return Nrf::MatterBridgedDevice::DeviceType::GenericSwitch; } CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) override; diff --git a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp index 4d7558f7a89..e2092078b15 100644 --- a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp +++ b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.cpp @@ -15,6 +15,7 @@ IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(humiSensorAttrs) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, INT16U, 2, 0), @@ -26,11 +27,13 @@ DECLARE_DYNAMIC_ATTRIBUTE(Clusters::RelativeHumidityMeasurement::Attributes::Mea DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedHumidityClusters) -DECLARE_DYNAMIC_CLUSTER(Clusters::RelativeHumidityMeasurement::Id, humiSensorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), +DECLARE_DYNAMIC_CLUSTER(Clusters::RelativeHumidityMeasurement::Id, humiSensorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, + nullptr), DECLARE_DYNAMIC_CLUSTER(Clusters::Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), sIdentifyIncomingCommands, - nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, + ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), + sIdentifyIncomingCommands, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(bridgedHumidityEndpoint, bridgedHumidityClusters); diff --git a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h index c3d5db7c5aa..52ce5813e42 100644 --- a/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h +++ b/applications/matter_bridge/src/bridged_device_types/humidity_sensor.h @@ -8,23 +8,15 @@ #include "matter_bridged_device.h" -class HumiditySensorDevice : public MatterBridgedDevice { +class HumiditySensorDevice : public Nrf::MatterBridgedDevice { public: - static constexpr uint16_t kRelativeHumidityMeasurementClusterRevision = 4; - static constexpr uint32_t kRelativeHumidityMeasurementFeatureMap = 0; - HumiditySensorDevice(const char *nodeLabel); uint16_t GetMeasuredValue() { return mMeasuredValue; } uint16_t GetMinMeasuredValue() { return mMinMeasuredValue; } uint16_t GetMaxMeasuredValue() { return mMaxMeasuredValue; } - uint16_t GetRelativeHumidityMeasurementClusterRevision() { return kRelativeHumidityMeasurementClusterRevision; } - uint32_t GetRelativeHumidityMeasurementFeatureMap() { return kRelativeHumidityMeasurementFeatureMap; } - uint16_t GetDeviceType() const override - { - return MatterBridgedDevice::DeviceType::HumiditySensor; - } + uint16_t GetDeviceType() const override { return Nrf::MatterBridgedDevice::DeviceType::HumiditySensor; } CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) override; CHIP_ERROR HandleReadRelativeHumidityMeasurement(chip::AttributeId attributeId, uint8_t *buffer, @@ -36,6 +28,9 @@ class HumiditySensorDevice : public MatterBridgedDevice { CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) override; + static constexpr uint16_t GetRelativeHumidityMeasurementClusterRevision() { return 3; } + static constexpr uint32_t GetRelativeHumidityMeasurementFeatureMap() { return 0; } + private: void SetMeasuredValue(int16_t value) { mMeasuredValue = value; } void SetMinMeasuredValue(int16_t value) { mMinMeasuredValue = value; } diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp index a08d3d2cea4..87b0255f97e 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp @@ -21,19 +21,36 @@ IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; + +constexpr CommandId identifyIncomingCommands[] = { + app::Clusters::Identify::Commands::Identify::Id, + app::Clusters::Identify::Commands::TriggerEffect::Id, + kInvalidCommandId, +}; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(onOffAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::OnOff::Id, BOOLEAN, 1, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::OnOff::Id, BOOLEAN, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::FeatureMap::Id, BITMAP32, 4, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::GlobalSceneControl::Id, BOOLEAN, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::OnTime::Id, INT16U, 2, ZAP_ATTRIBUTE_MASK(WRITABLE)), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::OffWaitTime::Id, INT16U, 2, ZAP_ATTRIBUTE_MASK(WRITABLE)), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::StartUpOnOff::Id, ENUM8, 1, ZAP_ATTRIBUTE_MASK(WRITABLE)), + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); constexpr CommandId onOffIncomingCommands[] = { app::Clusters::OnOff::Commands::Off::Id, app::Clusters::OnOff::Commands::On::Id, app::Clusters::OnOff::Commands::Toggle::Id, + app::Clusters::OnOff::Commands::OffWithEffect::Id, + app::Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id, + app::Clusters::OnOff::Commands::OnWithTimedOff::Id, kInvalidCommandId, }; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(groupsAttrs) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::Groups::Attributes::NameSupport::Id, BITMAP8, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(Clusters::Groups::Attributes::FeatureMap::Id, BITMAP32, 4, 1), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); constexpr CommandId groupsIncomingCommands[] = { @@ -46,13 +63,23 @@ constexpr CommandId groupsIncomingCommands[] = { kInvalidCommandId, }; +constexpr CommandId groupsGeneratedCommands[] = { + app::Clusters::Groups::Commands::AddGroupResponse::Id, + app::Clusters::Groups::Commands::RemoveGroupResponse::Id, + app::Clusters::Groups::Commands::ViewGroupResponse::Id, + app::Clusters::Groups::Commands::GetGroupMembershipResponse::Id, + kInvalidCommandId, +}; + DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters) DECLARE_DYNAMIC_CLUSTER(Clusters::OnOff::Id, onOffAttrs, ZAP_CLUSTER_MASK(SERVER), onOffIncomingCommands, nullptr), DECLARE_DYNAMIC_CLUSTER(Clusters::Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::Groups::Id, groupsAttrs, ZAP_CLUSTER_MASK(SERVER), groupsIncomingCommands, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), sIdentifyIncomingCommands, - nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + DECLARE_DYNAMIC_CLUSTER(Clusters::Groups::Id, groupsAttrs, ZAP_CLUSTER_MASK(SERVER), groupsIncomingCommands, + groupsGeneratedCommands), + DECLARE_DYNAMIC_CLUSTER(Clusters::BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, + ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), + identifyIncomingCommands, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters); @@ -103,6 +130,18 @@ CHIP_ERROR OnOffLightDevice::HandleReadOnOff(AttributeId attributeId, uint8_t *b uint32_t featureMap = GetOnOffFeatureMap(); return CopyAttribute(&featureMap, sizeof(featureMap), buffer, maxReadLength); } + case Clusters::OnOff::Attributes::OnTime::Id: { + return CopyAttribute(&mOnTime, sizeof(mOnTime), buffer, maxReadLength); + } + case Clusters::OnOff::Attributes::OffWaitTime::Id: { + return CopyAttribute(&mOffWaitTime, sizeof(mOffWaitTime), buffer, maxReadLength); + } + case Clusters::OnOff::Attributes::StartUpOnOff::Id: { + return CopyAttribute(&mStartUpOnOff, sizeof(mStartUpOnOff), buffer, maxReadLength); + } + case Clusters::OnOff::Attributes::GlobalSceneControl::Id: { + return CopyAttribute(&mGlobalSceneControl, sizeof(mGlobalSceneControl), buffer, maxReadLength); + } default: return CHIP_ERROR_INVALID_ARGUMENT; } @@ -135,13 +174,22 @@ CHIP_ERROR OnOffLightDevice::HandleWrite(ClusterId clusterId, AttributeId attrib } switch (attributeId) { - case Clusters::OnOff::Attributes::OnOff::Id: { - SetOnOff(*buffer); - return CHIP_NO_ERROR; - } + case Clusters::OnOff::Attributes::OnOff::Id: + mOnOff = *buffer; + break; + case Clusters::OnOff::Attributes::OnTime::Id: + mOnTime = *buffer; + break; + case Clusters::OnOff::Attributes::OffWaitTime::Id: + mOffWaitTime = *buffer; + break; + case Clusters::OnOff::Attributes::StartUpOnOff::Id: + mStartUpOnOff = static_cast(*buffer); + break; default: return CHIP_ERROR_INVALID_ARGUMENT; } + return CHIP_NO_ERROR; } CHIP_ERROR OnOffLightDevice::HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, @@ -167,8 +215,7 @@ CHIP_ERROR OnOffLightDevice::HandleAttributeChange(chip::ClusterId clusterId, ch if (err != CHIP_NO_ERROR) { return err; } - - SetOnOff(value); + mOnOff = value; break; } default: diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light.h b/applications/matter_bridge/src/bridged_device_types/onoff_light.h index 50168fc7df9..4226a009f85 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light.h +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light.h @@ -7,28 +7,15 @@ #pragma once #include "matter_bridged_device.h" -class OnOffLightDevice : public MatterBridgedDevice { -public: - static constexpr uint16_t kOnOffClusterRevision = 4; - static constexpr uint32_t kOnOffFeatureMap = 1; - static constexpr uint16_t kGroupsClusterRevision = 4; - static constexpr uint32_t kGroupsFeatureMap = 0; - static constexpr uint8_t kGroupsNameSupportMap = 0; +class OnOffLightDevice : public Nrf::MatterBridgedDevice { +public: OnOffLightDevice(const char *nodeLabel); bool GetOnOff() { return mOnOff; } void Toggle() { mOnOff = !mOnOff; } - uint16_t GetOnOffClusterRevision() { return kOnOffClusterRevision; } - uint32_t GetOnOffFeatureMap() { return kOnOffFeatureMap; } - uint16_t GetGroupsClusterRevision() { return kGroupsClusterRevision; } - uint32_t GetGroupsFeatureMap() { return kGroupsFeatureMap; } - uint8_t GetGroupsNameSupportMap() { return kGroupsNameSupportMap; } - uint16_t GetDeviceType() const override - { - return MatterBridgedDevice::DeviceType::OnOffLight; - } + uint16_t GetDeviceType() const override { return Nrf::MatterBridgedDevice::DeviceType::OnOffLight; } CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) override; CHIP_ERROR HandleReadOnOff(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); @@ -37,8 +24,18 @@ class OnOffLightDevice : public MatterBridgedDevice { CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) override; -private: - void SetOnOff(bool onOff) { mOnOff = onOff; } + static constexpr uint16_t GetOnOffClusterRevision() { return 5; } + static constexpr uint32_t GetOnOffFeatureMap() { return 1; } + static constexpr uint16_t GetGroupsClusterRevision() { return 4; } + static constexpr uint32_t GetGroupsFeatureMap() { return 1; } + static constexpr uint8_t GetGroupsNameSupportMap() { return 0; } - bool mOnOff = false; +private: + bool mOnOff{ false }; + bool mGlobalSceneControl{ false }; + int16_t mOnTime{ 0 }; + int16_t mOffWaitTime{ 0 }; + chip::app::Clusters::OnOff::StartUpOnOffEnum mStartUpOnOff{ + chip::app::Clusters::OnOff::StartUpOnOffEnum::kUnknownEnumValue + }; }; diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.cpp b/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.cpp index 6d3d9ad0f34..699d1cbc12b 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.cpp +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.cpp @@ -21,6 +21,7 @@ IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(onOffClientAttrs) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::OnOff::Attributes::FeatureMap::Id, BITMAP32, 4, 0), @@ -47,19 +48,21 @@ DECLARE_DYNAMIC_CLUSTER(Clusters::OnOff::Id, onOffClientAttrs, ZAP_CLUSTER_MASK( ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(SERVER), sIdentifyIncomingCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(Clusters::Identify::Id, identifyAttrs, ZAP_CLUSTER_MASK(CLIENT), + sIdentifyIncomingCommands, nullptr), DECLARE_DYNAMIC_CLUSTER(Clusters::Binding::Id, bindingAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(bridgedLightSwitchEndpoint, bridgedLightSwitchClusters); -static constexpr uint8_t kBridgedOnOffLightSwitchEndpointVersion = 2 +static constexpr uint8_t kBridgedOnOffLightSwitchEndpointVersion = 2; - static constexpr EmberAfDeviceType kBridgedLightSwitchDeviceTypes[] = { - { static_cast(MatterBridgedDevice::DeviceType::OnOffLightSwitch), - kBridgedOnOffLightSwitchEndpointVersion }, - { static_cast(MatterBridgedDevice::DeviceType::BridgedNode), - MatterBridgedDevice::kDefaultDynamicEndpointVersion } - }; +static constexpr EmberAfDeviceType kBridgedLightSwitchDeviceTypes[] = { + { static_cast(MatterBridgedDevice::DeviceType::OnOffLightSwitch), + kBridgedOnOffLightSwitchEndpointVersion }, + { static_cast(MatterBridgedDevice::DeviceType::BridgedNode), + MatterBridgedDevice::kDefaultDynamicEndpointVersion } +}; static constexpr uint8_t kLightSwitchDataVersionSize = ArraySize(bridgedLightSwitchClusters); @@ -80,6 +83,24 @@ CHIP_ERROR OnOffLightSwitchDevice::HandleRead(ClusterId clusterId, AttributeId a return HandleReadOnOff(attributeId, buffer, maxReadLength); case Clusters::Identify::Id: return HandleReadIdentify(attributeId, buffer, maxReadLength); + case Clusters::Binding::Id: + return HandleReadBinding(attributeId, buffer, maxReadLength); + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } +} + +CHIP_ERROR OnOffLightSwitchDevice::HandleReadBinding(AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) +{ + switch (attributeId) { + case Clusters::Binding::Attributes::FeatureMap::Id: { + uint32_t featureMap = GetBindingFeatureMap(); + return CopyAttribute(&featureMap, sizeof(featureMap), buffer, maxReadLength); + } + case Clusters::Binding::Attributes::ClusterRevision::Id: { + uint16_t clusterRevision = GetBindingClusterRevision(); + return CopyAttribute(&clusterRevision, sizeof(clusterRevision), buffer, maxReadLength); + } default: return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.h b/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.h index 689f39fd815..7382fd13ce6 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.h +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light_switch.h @@ -8,27 +8,15 @@ #include "matter_bridged_device.h" -class OnOffLightSwitchDevice : public MatterBridgedDevice { +class OnOffLightSwitchDevice : public Nrf::MatterBridgedDevice { public: - static constexpr uint16_t kOnOffClusterRevision = 4; - static constexpr uint32_t kOnOffFeatureMap = 1; - static constexpr uint16_t kBindingClusterRevision = 1; - static constexpr uint32_t kBindingFeatureMap = 0; - OnOffLightSwitchDevice(const char *nodeLabel); - uint16_t GetOnOffClusterRevision() { return kOnOffClusterRevision; } - uint32_t GetOnOffFeatureMap() { return kOnOffFeatureMap; } - uint16_t GetBindingClusterRevision() { return kBindingClusterRevision; } - uint32_t GetBindingFeatureMap() { return kBindingFeatureMap; } - - MatterBridgedDevice::DeviceType GetDeviceType() const override - { - return MatterBridgedDevice::DeviceType::OnOffLightSwitch; - } + uint16_t GetDeviceType() const override { return Nrf::MatterBridgedDevice::DeviceType::OnOffLightSwitch; } CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) override; CHIP_ERROR HandleReadOnOff(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); + CHIP_ERROR HandleReadBinding(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); CHIP_ERROR HandleWrite(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) override { return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; @@ -39,5 +27,8 @@ class OnOffLightSwitchDevice : public MatterBridgedDevice { return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } -private: + static constexpr uint16_t GetOnOffClusterRevision() { return 4; } + static constexpr uint32_t GetOnOffFeatureMap() { return 1; } + static constexpr uint16_t GetBindingClusterRevision() { return 1; } + static constexpr uint32_t GetBindingFeatureMap() { return 0; } }; diff --git a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp index d5dbba5eaad..0a52e0de0ba 100644 --- a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp +++ b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.cpp @@ -15,6 +15,7 @@ IDENTIFY_CLUSTER_ATTRIBUTES(identifyAttrs); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(tempSensorAttrs) DECLARE_DYNAMIC_ATTRIBUTE(Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Id, INT16S, 2, 0), diff --git a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h index 71408dd690b..7f07a7a2728 100644 --- a/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h +++ b/applications/matter_bridge/src/bridged_device_types/temperature_sensor.h @@ -8,23 +8,15 @@ #include "matter_bridged_device.h" -class TemperatureSensorDevice : public MatterBridgedDevice { +class TemperatureSensorDevice : public Nrf::MatterBridgedDevice { public: - static constexpr uint16_t kTemperatureMeasurementClusterRevision = 4; - static constexpr uint32_t kTemperatureMeasurementFeatureMap = 0; - TemperatureSensorDevice(const char *nodeLabel); int16_t GetMeasuredValue() { return mMeasuredValue; } int16_t GetMinMeasuredValue() { return mMinMeasuredValue; } int16_t GetMaxMeasuredValue() { return mMaxMeasuredValue; } - uint16_t GetTemperatureMeasurementClusterRevision() { return kTemperatureMeasurementClusterRevision; } - uint32_t GetTemperatureMeasurementFeatureMap() { return kTemperatureMeasurementFeatureMap; } - uint16_t GetDeviceType() const override - { - return MatterBridgedDevice::DeviceType::TemperatureSensor; - } + uint16_t GetDeviceType() const override { return Nrf::MatterBridgedDevice::DeviceType::TemperatureSensor; } CHIP_ERROR HandleRead(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) override; CHIP_ERROR HandleReadTemperatureMeasurement(chip::AttributeId attributeId, uint8_t *buffer, @@ -36,6 +28,9 @@ class TemperatureSensorDevice : public MatterBridgedDevice { CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) override; + static constexpr uint16_t GetTemperatureMeasurementClusterRevision() { return 4; } + static constexpr uint32_t GetTemperatureMeasurementFeatureMap() { return 0; } + private: void SetMeasuredValue(int16_t value) { mMeasuredValue = value; } void SetMinMeasuredValue(int16_t value) { mMinMeasuredValue = value; } diff --git a/applications/matter_bridge/src/chip_project_config.h b/applications/matter_bridge/src/chip_project_config.h index 60eee35b999..f6c66f0e8e4 100644 --- a/applications/matter_bridge/src/chip_project_config.h +++ b/applications/matter_bridge/src/chip_project_config.h @@ -15,4 +15,11 @@ #pragma once +#define CHIP_CONFIG_LOG_MODULE_Zcl_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_InteractionModel_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_InteractionModel_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_DataManagement_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_FabricProvisioning_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_SecureChannel_PROGRESS 0 + #define CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT CONFIG_BRIDGE_MAX_DYNAMIC_ENDPOINTS_NUMBER diff --git a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp index 267e479cc57..df2a06e8433 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.cpp @@ -14,19 +14,19 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); namespace { -CHIP_ERROR StoreDevice(MatterBridgedDevice *device, BridgedDeviceDataProvider *provider, uint8_t index) +CHIP_ERROR StoreDevice(Nrf::MatterBridgedDevice *device, Nrf::BridgedDeviceDataProvider *provider, uint8_t index) { uint16_t endpointId; uint8_t count = 0; - uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 }; + uint8_t indexes[Nrf::BridgeManager::kMaxBridgedDevices] = { 0 }; bool deviceRefresh = false; /* Check if a device is already present in the storage. */ - if (BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, index)) { + if (Nrf::BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, index)) { deviceRefresh = true; } - if (!BridgeStorageManager::Instance().StoreBridgedDevice(device, index)) { + if (!Nrf::BridgeStorageManager::Instance().StoreBridgedDevice(device, index)) { LOG_ERR("Failed to store bridged device"); return CHIP_ERROR_INTERNAL; } @@ -34,18 +34,18 @@ CHIP_ERROR StoreDevice(MatterBridgedDevice *device, BridgedDeviceDataProvider *p /* If a device was not present in the storage before, put new index on the end of list and increment the count * number of stored devices. */ if (!deviceRefresh) { - CHIP_ERROR err = BridgeManager::Instance().GetDevicesIndexes(indexes, sizeof(indexes), count); + CHIP_ERROR err = Nrf::BridgeManager::Instance().GetDevicesIndexes(indexes, sizeof(indexes), count); if (CHIP_NO_ERROR != err) { LOG_ERR("Failed to get bridged devices indexes"); return err; } - if (!BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, count)) { + if (!Nrf::BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, count)) { LOG_ERR("Failed to store bridged devices indexes."); return CHIP_ERROR_INTERNAL; } - if (!BridgeStorageManager::Instance().StoreBridgedDevicesCount(count)) { + if (!Nrf::BridgeStorageManager::Instance().StoreBridgedDevicesCount(count)) { LOG_ERR("Failed to store bridged devices count."); return CHIP_ERROR_INTERNAL; } @@ -59,7 +59,7 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto { auto checkLabel = [](const char *nodeLabel) { /* If node label is provided it must fit the maximum defined length */ - if (!nodeLabel || (nodeLabel && (strlen(nodeLabel) < MatterBridgedDevice::kNodeLabelSize))) { + if (!nodeLabel || (nodeLabel && (strlen(nodeLabel) < Nrf::MatterBridgedDevice::kNodeLabelSize))) { return true; } return false; @@ -67,8 +67,8 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto static BridgedDeviceFactory sBridgedDeviceFactory{ #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::OnOffLight, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + { Nrf::MatterBridgedDevice::DeviceType::OnOffLight, + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } @@ -76,8 +76,8 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::GenericSwitch, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + { Nrf::MatterBridgedDevice::DeviceType::GenericSwitch, + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } @@ -85,8 +85,8 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::OnOffLightSwitch, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + { Nrf::MatterBridgedDevice::DeviceType::OnOffLightSwitch, + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } @@ -94,8 +94,8 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::TemperatureSensor, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + { Nrf::MatterBridgedDevice::DeviceType::TemperatureSensor, + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } @@ -103,8 +103,8 @@ SimulatedBridgedDeviceFactory::BridgedDeviceFactory &SimulatedBridgedDeviceFacto } }, #endif #ifdef CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::HumiditySensor, - [checkLabel](const char *nodeLabel) -> MatterBridgedDevice * { + { Nrf::MatterBridgedDevice::DeviceType::HumiditySensor, + [checkLabel](const char *nodeLabel) -> Nrf::MatterBridgedDevice * { if (!checkLabel(nodeLabel)) { return nullptr; } @@ -119,31 +119,31 @@ SimulatedBridgedDeviceFactory::SimulatedDataProviderFactory &SimulatedBridgedDev { static SimulatedDataProviderFactory sDeviceDataProvider{ #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::OnOffLight, + { Nrf::MatterBridgedDevice::DeviceType::OnOffLight, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_GENERIC_SWITCH_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::GenericSwitch, + { Nrf::MatterBridgedDevice::DeviceType::GenericSwitch, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_ONOFF_LIGHT_SWITCH_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::OnOffLightSwitch, + { Nrf::MatterBridgedDevice::DeviceType::OnOffLightSwitch, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_TEMPERATURE_SENSOR_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::TemperatureSensor, + { Nrf::MatterBridgedDevice::DeviceType::TemperatureSensor, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, #endif #ifdef CONFIG_BRIDGE_HUMIDITY_SENSOR_BRIDGED_DEVICE - { MatterBridgedDevice::DeviceType::HumiditySensor, + { Nrf::MatterBridgedDevice::DeviceType::HumiditySensor, [](UpdateAttributeCallback updateClb, InvokeCommandCallback commandClb) { return chip::Platform::New(updateClb, commandClb); } }, @@ -158,15 +158,15 @@ CHIP_ERROR SimulatedBridgedDeviceFactory::CreateDevice(int deviceType, const cha { CHIP_ERROR err; - BridgedDeviceDataProvider *provider = GetDataProviderFactory().Create( - static_cast(deviceType), BridgeManager::HandleUpdate, BridgeManager::HandleCommand); + Nrf::BridgedDeviceDataProvider *provider = GetDataProviderFactory().Create( + static_cast(deviceType), Nrf::BridgeManager::HandleUpdate, Nrf::BridgeManager::HandleCommand); VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT, LOG_ERR("No valid data provider!")); auto *newBridgedDevice = - GetBridgedDeviceFactory().Create(static_cast(deviceType), nodeLabel); + GetBridgedDeviceFactory().Create(static_cast(deviceType), nodeLabel); - MatterBridgedDevice *newBridgedDevices[] = { newBridgedDevice }; + Nrf::MatterBridgedDevice *newBridgedDevices[] = { newBridgedDevice }; if (!newBridgedDevice) { LOG_ERR("Cannot allocate Matter device of given type"); @@ -181,10 +181,10 @@ CHIP_ERROR SimulatedBridgedDeviceFactory::CreateDevice(int deviceType, const cha if (index.HasValue() && endpointId.HasValue()) { endpointIds[0] = endpointId.Value(); deviceIndex[0] = index.Value(); - err = BridgeManager::Instance().AddBridgedDevices( + err = Nrf::BridgeManager::Instance().AddBridgedDevices( newBridgedDevices, provider, ARRAY_SIZE(newBridgedDevices), deviceIndex, endpointIds); } else { - err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, provider, + err = Nrf::BridgeManager::Instance().AddBridgedDevices(newBridgedDevices, provider, ARRAY_SIZE(newBridgedDevices), deviceIndex); } @@ -205,41 +205,41 @@ CHIP_ERROR SimulatedBridgedDeviceFactory::RemoveDevice(int endpointId) { uint8_t index; uint8_t count = 0; - uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 }; + uint8_t indexes[Nrf::BridgeManager::kMaxBridgedDevices] = { 0 }; - CHIP_ERROR err = BridgeManager::Instance().RemoveBridgedDevice(endpointId, index); + CHIP_ERROR err = Nrf::BridgeManager::Instance().RemoveBridgedDevice(endpointId, index); if (CHIP_NO_ERROR != err) { LOG_ERR("Failed to remove bridged device"); return err; } - err = BridgeManager::Instance().GetDevicesIndexes(indexes, sizeof(indexes), count); + err = Nrf::BridgeManager::Instance().GetDevicesIndexes(indexes, sizeof(indexes), count); if (CHIP_NO_ERROR != err) { LOG_ERR("Failed to get bridged devices indexes"); return err; } /* Update the current indexes list. */ - if (!BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, count)) { + if (!Nrf::BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, count)) { LOG_ERR("Failed to store bridged devices indexes."); return CHIP_ERROR_INTERNAL; } - if (!BridgeStorageManager::Instance().StoreBridgedDevicesCount(count)) { + if (!Nrf::BridgeStorageManager::Instance().StoreBridgedDevicesCount(count)) { LOG_ERR("Failed to store bridged devices count."); return CHIP_ERROR_INTERNAL; } - if (!BridgeStorageManager::Instance().RemoveBridgedDeviceEndpointId(index)) { + if (!Nrf::BridgeStorageManager::Instance().RemoveBridgedDeviceEndpointId(index)) { LOG_ERR("Failed to remove bridged device endpoint id."); return CHIP_ERROR_INTERNAL; } /* Ignore error, as node label may not be present in the storage. */ - BridgeStorageManager::Instance().RemoveBridgedDeviceNodeLabel(index); + Nrf::BridgeStorageManager::Instance().RemoveBridgedDeviceNodeLabel(index); - if (!BridgeStorageManager::Instance().RemoveBridgedDeviceType(index)) { + if (!Nrf::BridgeStorageManager::Instance().RemoveBridgedDeviceType(index)) { LOG_ERR("Failed to remove bridged device type."); return CHIP_ERROR_INTERNAL; } diff --git a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h index ffa7de766c3..0604a03e894 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_bridged_device_factory.h @@ -38,11 +38,11 @@ namespace SimulatedBridgedDeviceFactory { -using UpdateAttributeCallback = BridgedDeviceDataProvider::UpdateAttributeCallback; -using InvokeCommandCallback = BridgedDeviceDataProvider::InvokeCommandCallback; +using UpdateAttributeCallback = Nrf::BridgedDeviceDataProvider::UpdateAttributeCallback; +using InvokeCommandCallback = Nrf::BridgedDeviceDataProvider::InvokeCommandCallback; using DeviceType = uint16_t; -using BridgedDeviceFactory = DeviceFactory; -using SimulatedDataProviderFactory = DeviceFactory; +using BridgedDeviceFactory = Nrf::DeviceFactory; +using SimulatedDataProviderFactory = Nrf::DeviceFactory; BridgedDeviceFactory &GetBridgedDeviceFactory(); SimulatedDataProviderFactory &GetDataProviderFactory(); diff --git a/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.cpp b/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.cpp index c88956ba29c..76f62142d0e 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.cpp @@ -12,6 +12,7 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; void SimulatedGenericSwitchDataProvider::Init() { @@ -46,7 +47,7 @@ CHIP_ERROR SimulatedGenericSwitchDataProvider::UpdateState(chip::ClusterId clust return CHIP_NO_ERROR; } default: - return CHIP_ERROR_INVALID_ARGUMENT; + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } return CHIP_NO_ERROR; diff --git a/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.h b/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.h index 54a8a11fe40..08e60abfd08 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_generic_switch_data_provider.h @@ -8,9 +8,9 @@ #include "bridged_device_data_provider.h" -class SimulatedGenericSwitchDataProvider : public BridgedDeviceDataProvider { +class SimulatedGenericSwitchDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedGenericSwitchDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + SimulatedGenericSwitchDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) {} ~SimulatedGenericSwitchDataProvider() { k_timer_stop(&mTimer); } void Init() override; diff --git a/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.cpp b/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.cpp index 4269d679fbf..883b9f5e5ba 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.cpp @@ -12,6 +12,7 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; void SimulatedHumiditySensorDataProvider::Init() { diff --git a/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.h b/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.h index 8bce04ee8ed..2402364a07a 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_humidity_sensor_data_provider.h @@ -8,9 +8,9 @@ #include "bridged_device_data_provider.h" -class SimulatedHumiditySensorDataProvider : public BridgedDeviceDataProvider { +class SimulatedHumiditySensorDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedHumiditySensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + SimulatedHumiditySensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) {} ~SimulatedHumiditySensorDataProvider() { k_timer_stop(&mTimer); } void Init() override; void NotifyUpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, diff --git a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.cpp b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.cpp index 33f39f23bd7..4bd25daa0de 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.cpp @@ -12,6 +12,7 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; void SimulatedOnOffLightDataProvider::Init() { @@ -48,7 +49,7 @@ CHIP_ERROR SimulatedOnOffLightDataProvider::UpdateState(chip::ClusterId clusterI return CHIP_NO_ERROR; } default: - return CHIP_ERROR_INVALID_ARGUMENT; + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } return CHIP_NO_ERROR; diff --git a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.h b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.h index 97e208ab531..2082b36224e 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_data_provider.h @@ -8,9 +8,9 @@ #include "bridged_device_data_provider.h" -class SimulatedOnOffLightDataProvider : public BridgedDeviceDataProvider { +class SimulatedOnOffLightDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedOnOffLightDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + SimulatedOnOffLightDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) {} ~SimulatedOnOffLightDataProvider() { #ifdef CONFIG_BRIDGED_DEVICE_SIMULATED_ONOFF_AUTOMATIC diff --git a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.cpp b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.cpp index 7946d623be0..1777629a195 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.cpp @@ -13,6 +13,7 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; void SimulatedOnOffLightSwitchDataProvider::Init() {} @@ -21,25 +22,19 @@ void SimulatedOnOffLightSwitchDataProvider::NotifyUpdateState(chip::ClusterId cl { } -void ProcessCommand(CommandId aCommandId, const EmberBindingTableEntry &aBinding, OperationalDeviceProxy *aDevice, - void *aContext) +void ProcessCommand(const EmberBindingTableEntry &aBinding, OperationalDeviceProxy *aDevice, + Nrf::Matter::BindingHandler::BindingData &aData) { CHIP_ERROR ret = CHIP_NO_ERROR; - BindingHandler::BindingData *data = reinterpret_cast(aContext); - auto onSuccess = [dataRef = data](const ConcreteCommandPath &commandPath, const StatusIB &status, - const auto &dataResponse) { - LOG_DBG("Binding command applied successfully!"); + auto onSuccess = [dataRef = Platform::New(aData)]( + const ConcreteCommandPath &commandPath, const StatusIB &status, + const auto &dataResponse) { Matter::BindingHandler::OnInvokeCommandSucces(dataRef); }; - /* If session was recovered and communication works, reset flag to the initial state. */ - if (dataRef->CaseSessionRecovered) { - dataRef->CaseSessionRecovered = false; - } - }; - - auto onFailure = [dataRef = *data](CHIP_ERROR aError) mutable { - BindingHandler::OnInvokeCommandFailure(dataRef, aError); - }; + auto onFailure = + [dataRef = Platform::New(aData)](CHIP_ERROR aError) mutable { + Matter::BindingHandler::OnInvokeCommandFailure(dataRef, aError); + }; if (aDevice) { /* We are validating connection is ready once here instead of multiple times in each case statement @@ -66,10 +61,14 @@ void ProcessCommand(CommandId aCommandId, const EmberBindingTableEntry &aBinding CHIP_ERROR SimulatedOnOffLightSwitchDataProvider::UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) { - if (clusterId != Clusters::OnOff::Id || attributeId != Clusters::OnOff::Attributes::OnOff::Id) { + if (clusterId != Clusters::OnOff::Id) { return CHIP_ERROR_INVALID_ARGUMENT; } + if (attributeId != Clusters::OnOff::Attributes::OnOff::Id) { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + bool mOnOff; memcpy(&mOnOff, buffer, sizeof(mOnOff)); diff --git a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.h b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.h index 1160650a950..c976c7d434a 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_onoff_light_switch_data_provider.h @@ -8,9 +8,9 @@ #include "bridged_device_data_provider.h" -class SimulatedOnOffLightSwitchDataProvider : public BridgedDeviceDataProvider { +class SimulatedOnOffLightSwitchDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedOnOffLightSwitchDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {} + SimulatedOnOffLightSwitchDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) {} ~SimulatedOnOffLightSwitchDataProvider() {} void Init() override; diff --git a/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.cpp b/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.cpp index 5954894281e..56b3816351f 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.cpp +++ b/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.cpp @@ -12,6 +12,7 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); using namespace ::chip; using namespace ::chip::app; +using namespace Nrf; void SimulatedTemperatureSensorDataProvider::Init() { diff --git a/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.h b/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.h index 143aff2435b..dab89ffb290 100644 --- a/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.h +++ b/applications/matter_bridge/src/simulated_providers/simulated_temperature_sensor_data_provider.h @@ -10,9 +10,9 @@ #include -class SimulatedTemperatureSensorDataProvider : public BridgedDeviceDataProvider { +class SimulatedTemperatureSensorDataProvider : public Nrf::BridgedDeviceDataProvider { public: - SimulatedTemperatureSensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) + SimulatedTemperatureSensorDataProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : Nrf::BridgedDeviceDataProvider(updateCallback, commandCallback) { } ~SimulatedTemperatureSensorDataProvider() { k_timer_stop(&mTimer); } diff --git a/applications/matter_bridge/src/zap-generated/CHIPClusters.h b/applications/matter_bridge/src/zap-generated/CHIPClusters.h index 326a58b94cf..7bf9ba30ac6 100644 --- a/applications/matter_bridge/src/zap-generated/CHIPClusters.h +++ b/applications/matter_bridge/src/zap-generated/CHIPClusters.h @@ -30,6 +30,16 @@ namespace chip namespace Controller { + class DLL_EXPORT IdentifyCluster : public ClusterBase { + public: + IdentifyCluster(Messaging::ExchangeManager &exchangeManager, const SessionHandle &session, + EndpointId endpoint) + : ClusterBase(exchangeManager, session, endpoint) + { + } + ~IdentifyCluster() {} + }; + class DLL_EXPORT OnOffCluster : public ClusterBase { public: OnOffCluster(Messaging::ExchangeManager &exchangeManager, const SessionHandle &session, diff --git a/applications/matter_bridge/src/zap-generated/IMClusterCommandHandler.cpp b/applications/matter_bridge/src/zap-generated/IMClusterCommandHandler.cpp index 9ab25869053..6e411114963 100644 --- a/applications/matter_bridge/src/zap-generated/IMClusterCommandHandler.cpp +++ b/applications/matter_bridge/src/zap-generated/IMClusterCommandHandler.cpp @@ -513,6 +513,33 @@ namespace app } break; } + case Commands::OffWithEffect::Id: { + Commands::OffWithEffect::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { + wasHandled = emberAfOnOffClusterOffWithEffectCallback( + apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::OnWithRecallGlobalScene::Id: { + Commands::OnWithRecallGlobalScene::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { + wasHandled = emberAfOnOffClusterOnWithRecallGlobalSceneCallback( + apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::OnWithTimedOff::Id: { + Commands::OnWithTimedOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { + wasHandled = emberAfOnOffClusterOnWithTimedOffCallback( + apCommandObj, aCommandPath, commandData); + } + break; + } default: { // Unrecognized command ID, error status will apply. apCommandObj->AddStatus( diff --git a/applications/matter_bridge/src/zap-generated/PluginApplicationCallbacks.h b/applications/matter_bridge/src/zap-generated/PluginApplicationCallbacks.h index 36bd27315d6..622a33eb5cf 100644 --- a/applications/matter_bridge/src/zap-generated/PluginApplicationCallbacks.h +++ b/applications/matter_bridge/src/zap-generated/PluginApplicationCallbacks.h @@ -33,6 +33,7 @@ void MatterGeneralDiagnosticsPluginServerInitCallback(); void MatterSoftwareDiagnosticsPluginServerInitCallback(); void MatterWiFiNetworkDiagnosticsPluginServerInitCallback(); void MatterBridgedDeviceBasicInformationPluginServerInitCallback(); +void MatterSwitchPluginServerInitCallback(); void MatterAdministratorCommissioningPluginServerInitCallback(); void MatterOperationalCredentialsPluginServerInitCallback(); void MatterGroupKeyManagementPluginServerInitCallback(); @@ -54,6 +55,7 @@ void MatterRelativeHumidityMeasurementPluginServerInitCallback(); MatterSoftwareDiagnosticsPluginServerInitCallback(); \ MatterWiFiNetworkDiagnosticsPluginServerInitCallback(); \ MatterBridgedDeviceBasicInformationPluginServerInitCallback(); \ + MatterSwitchPluginServerInitCallback(); \ MatterAdministratorCommissioningPluginServerInitCallback(); \ MatterOperationalCredentialsPluginServerInitCallback(); \ MatterGroupKeyManagementPluginServerInitCallback(); \ diff --git a/applications/matter_bridge/src/zap-generated/callback-stub.cpp b/applications/matter_bridge/src/zap-generated/callback-stub.cpp index f15f4d62dcc..6cdd237ab50 100644 --- a/applications/matter_bridge/src/zap-generated/callback-stub.cpp +++ b/applications/matter_bridge/src/zap-generated/callback-stub.cpp @@ -82,6 +82,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case app::Clusters::SoftwareDiagnostics::Id: emberAfSoftwareDiagnosticsClusterInitCallback(endpoint); break; + case app::Clusters::Switch::Id: + emberAfSwitchClusterInitCallback(endpoint); + break; case app::Clusters::TemperatureMeasurement::Id: emberAfTemperatureMeasurementClusterInitCallback(endpoint); break; @@ -184,6 +187,11 @@ void __attribute__((weak)) emberAfSoftwareDiagnosticsClusterInitCallback(Endpoin // To prevent warning (void)endpoint; } +void __attribute__((weak)) emberAfSwitchClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void)endpoint; +} void __attribute__((weak)) emberAfTemperatureMeasurementClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/applications/matter_bridge/src/zap-generated/endpoint_config.h b/applications/matter_bridge/src/zap-generated/endpoint_config.h index 561978dd93a..56c3ad565ec 100644 --- a/applications/matter_bridge/src/zap-generated/endpoint_config.h +++ b/applications/matter_bridge/src/zap-generated/endpoint_config.h @@ -59,7 +59,7 @@ } // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 155 +#define GENERATED_ATTRIBUTE_COUNT 159 #define GENERATED_ATTRIBUTES \ { \ /* Endpoint: 0, Cluster: Descriptor (server) */ \ @@ -281,7 +281,7 @@ ZAP_ATTRIBUTE_MASK(WRITABLE) }, /* IdentifyTime */ \ { ZAP_SIMPLE_DEFAULT(0x00), 0x00000001, 1, ZAP_TYPE(ENUM8), 0 }, /* IdentifyType */ \ { ZAP_SIMPLE_DEFAULT(0), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), 0 }, /* FeatureMap */ \ - { ZAP_SIMPLE_DEFAULT(2), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ + { ZAP_SIMPLE_DEFAULT(4), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Descriptor (server) */ \ { ZAP_EMPTY_DEFAULT(), 0x00000000, 0, ZAP_TYPE(ARRAY), \ @@ -359,6 +359,12 @@ { ZAP_SIMPLE_DEFAULT(0), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), 0 }, /* FeatureMap */ \ { ZAP_SIMPLE_DEFAULT(2), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ \ + /* Endpoint: 2, Cluster: Switch (server) */ \ + { ZAP_SIMPLE_DEFAULT(2), 0x00000000, 1, ZAP_TYPE(INT8U), 0 }, /* NumberOfPositions */ \ + { ZAP_EMPTY_DEFAULT(), 0x00000001, 1, ZAP_TYPE(INT8U), 0 }, /* CurrentPosition */ \ + { ZAP_SIMPLE_DEFAULT(2), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), 0 }, /* FeatureMap */ \ + { ZAP_SIMPLE_DEFAULT(1), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ + \ /* Endpoint: 2, Cluster: Temperature Measurement (server) */ \ { ZAP_EMPTY_DEFAULT(), 0x00000000, 2, ZAP_TYPE(INT16S), ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* MeasuredValue \ */ \ @@ -381,7 +387,7 @@ } // clang-format off -#define GENERATED_EVENT_COUNT 6 +#define GENERATED_EVENT_COUNT 7 #define GENERATED_EVENTS { \ /* Endpoint: 0, Cluster: Basic Information (server) */ \ /* EventList (index=0) */ \ @@ -393,6 +399,9 @@ 0x00000000, /* StateTransition */ \ 0x00000001, /* VersionApplied */ \ 0x00000002, /* DownloadError */ \ + /* Endpoint: 2, Cluster: Switch (server) */ \ + /* EventList (index=6) */ \ + 0x00000001, /* InitialPress */ \ } // clang-format on @@ -509,13 +518,16 @@ 0x00000000 /* Off */, \ 0x00000001 /* On */, \ 0x00000002 /* Toggle */, \ + 0x00000040 /* OffWithEffect */, \ + 0x00000041 /* OnWithRecallGlobalScene */, \ + 0x00000042 /* OnWithTimedOff */, \ chip::kInvalidCommandId /* end of list */, \ } // clang-format on // This is an array of EmberAfCluster structures. -#define GENERATED_CLUSTER_COUNT 24 +#define GENERATED_CLUSTER_COUNT 26 // clang-format off #define GENERATED_CLUSTERS { \ { \ @@ -713,6 +725,19 @@ .eventList = nullptr, \ .eventCount = 0, \ },\ + { \ + /* Endpoint: 2, Cluster: Identify (client) */ \ + .clusterId = 0x00000003, \ + .attributes = ZAP_ATTRIBUTE_INDEX(106), \ + .attributeCount = 0, \ + .clusterSize = 0, \ + .mask = ZAP_CLUSTER_MASK(CLIENT), \ + .functions = NULL, \ + .acceptedCommandList = nullptr, \ + .generatedCommandList = nullptr, \ + .eventList = nullptr, \ + .eventCount = 0, \ + },\ { \ /* Endpoint: 2, Cluster: Identify (server) */ \ .clusterId = 0x00000003, \ @@ -804,10 +829,23 @@ .eventList = nullptr, \ .eventCount = 0, \ },\ + { \ + /* Endpoint: 2, Cluster: Switch (server) */ \ + .clusterId = 0x0000003B, \ + .attributes = ZAP_ATTRIBUTE_INDEX(145), \ + .attributeCount = 4, \ + .clusterSize = 8, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr, \ + .generatedCommandList = nullptr, \ + .eventList = ZAP_GENERATED_EVENTS_INDEX( 6 ), \ + .eventCount = 1, \ + },\ { \ /* Endpoint: 2, Cluster: Temperature Measurement (server) */ \ .clusterId = 0x00000402, \ - .attributes = ZAP_ATTRIBUTE_INDEX(145), \ + .attributes = ZAP_ATTRIBUTE_INDEX(149), \ .attributeCount = 5, \ .clusterSize = 12, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -820,7 +858,7 @@ { \ /* Endpoint: 2, Cluster: Relative Humidity Measurement (server) */ \ .clusterId = 0x00000405, \ - .attributes = ZAP_ATTRIBUTE_INDEX(150), \ + .attributes = ZAP_ATTRIBUTE_INDEX(154), \ .attributeCount = 5, \ .clusterSize = 12, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -834,12 +872,13 @@ // clang-format on -#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 22 +#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 23 // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 13, 98 }, { ZAP_CLUSTER_INDEX(13), 2, 13 }, { ZAP_CLUSTER_INDEX(15), 9, 713 }, \ + { ZAP_CLUSTER_INDEX(0), 13, 98 }, { ZAP_CLUSTER_INDEX(13), 2, 13 }, \ + { ZAP_CLUSTER_INDEX(15), 11, 721 }, \ } // Largest attribute size is needed for various buffers @@ -852,7 +891,7 @@ static_assert(ATTRIBUTE_LARGEST <= CHIP_CONFIG_MAX_ATTRIBUTE_STORE_ELEMENT_SIZE, #define ATTRIBUTE_SINGLETONS_SIZE (35) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (824) +#define ATTRIBUTE_MAX_SIZE (832) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (3) diff --git a/applications/matter_bridge/src/zap-generated/gen_config.h b/applications/matter_bridge/src/zap-generated/gen_config.h index 42cad1c6371..e0964e1e28d 100644 --- a/applications/matter_bridge/src/zap-generated/gen_config.h +++ b/applications/matter_bridge/src/zap-generated/gen_config.h @@ -21,6 +21,7 @@ #pragma once /**** Cluster endpoint counts ****/ +#define EMBER_AF_IDENTIFY_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT (2) #define EMBER_AF_GROUPS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ON_OFF_CLUSTER_CLIENT_ENDPOINT_COUNT (1) @@ -37,6 +38,7 @@ #define EMBER_AF_SOFTWARE_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_SWITCH_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_OPERATIONAL_CREDENTIALS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GROUP_KEY_MANAGEMENT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -45,6 +47,10 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the client side of the Identify cluster is included +#define ZCL_USING_IDENTIFY_CLUSTER_CLIENT +#define EMBER_AF_PLUGIN_IDENTIFY_CLIENT + // Use this macro to check if the server side of the Identify cluster is included #define ZCL_USING_IDENTIFY_CLUSTER_SERVER #define EMBER_AF_PLUGIN_IDENTIFY_SERVER @@ -123,6 +129,11 @@ #define EMBER_AF_PLUGIN_BRIDGED_DEVICE_BASIC_INFORMATION_SERVER #define EMBER_AF_PLUGIN_BRIDGED_DEVICE_BASIC_INFORMATION +// Use this macro to check if the server side of the Switch cluster is included +#define ZCL_USING_SWITCH_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_SWITCH_SERVER +#define EMBER_AF_PLUGIN_SWITCH + // Use this macro to check if the server side of the Administrator Commissioning cluster is included #define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER diff --git a/applications/matter_bridge/sysbuild.cmake b/applications/matter_bridge/sysbuild.cmake deleted file mode 100644 index 96fcb6969bc..00000000000 --- a/applications/matter_bridge/sysbuild.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Set the paritions configuration -set(PM_STATIC_YML_FILE ${ZEPHYR_NRF_MODULE_DIR}/applications/matter_bridge/configuration/${BOARD}/pm_static_dfu.yml PARENT_SCOPE) diff --git a/applications/matter_bridge/sysbuild/hci_ipc/prj.conf b/applications/matter_bridge/sysbuild/hci_ipc/prj.conf index a2b67dd57fd..2a266049549 100644 --- a/applications/matter_bridge/sysbuild/hci_ipc/prj.conf +++ b/applications/matter_bridge/sysbuild/hci_ipc/prj.conf @@ -17,11 +17,12 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 ## BT configuration CONFIG_BT=y CONFIG_BT_HCI_RAW=y -CONFIG_BT_MAX_CONN=1 +CONFIG_BT_MAX_CONN=10 CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_PERIPHERAL=y -CONFIG_BT_CENTRAL=n +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y CONFIG_BT_BUF_ACL_RX_SIZE=502 CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 diff --git a/applications/matter_weather_station/CMakeLists.txt b/applications/matter_weather_station/CMakeLists.txt index 9c1501a23b6..791b77e907a 100644 --- a/applications/matter_weather_station/CMakeLists.txt +++ b/applications/matter_weather_station/CMakeLists.txt @@ -6,34 +6,24 @@ cmake_minimum_required(VERSION 3.20.0) -################################################################################ - -# The application uses the configuration/ scheme for configuration files. -set(APPLICATION_CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configuration/\${BOARD}") - set(multiprotocol_rpmsg_KCONFIG_ROOT "\\\${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root") set(hci_ipc_KCONFIG_ROOT "\\\${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.hci_ipc.root") -if("${OVERLAY_CONFIG}" STREQUAL "overlay-factory_data.conf") - set(PM_STATIC_YML_FILE ${APPLICATION_CONFIG_DIR}/pm_static_factory_data.yml) -endif() - find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(matter-weather-station) -################################################################################ +project(matter-weather-station) -set(COMMON_ROOT ${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common) -set(NLIO_ROOT ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/third_party/nlio/repo) +# Enable GNU STD support and initialize the Matter Data Model. include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/app/enable-gnu-std.cmake) include(${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/src/app/chip_data_model.cmake) # NORDIC SDK APP START + +# Include all source files that are located in the Matter common directory. +include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/source_common.cmake) + target_include_directories(app PRIVATE src - ${COMMON_ROOT}/src - ${NLIO_ROOT}/include - ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/zzz_generated/app-common ) target_sources(app PRIVATE @@ -41,19 +31,8 @@ target_sources(app PRIVATE src/main.cpp src/battery.cpp src/buzzer.cpp - src/zap-generated/IMClusterCommandHandler.cpp - src/zap-generated/callback-stub.cpp - ${COMMON_ROOT}/src/led/led_widget.cpp - ${COMMON_ROOT}/src/dfu/smp/dfu_over_smp.cpp - ${COMMON_ROOT}/src/tasks/task_executor.cpp - ${COMMON_ROOT}/src/board/board.cpp - ${COMMON_ROOT}/src/init/matter_init.cpp ) -if(CONFIG_CHIP_OTA_REQUESTOR OR CONFIG_MCUMGR_TRANSPORT_BT) - target_sources(app PRIVATE ${COMMON_ROOT}/src/dfu/ota/ota_util.cpp) -endif() - chip_configure_data_model(app INCLUDE_SERVER BYPASS_IDL diff --git a/applications/matter_weather_station/Kconfig b/applications/matter_weather_station/Kconfig index 6fb3faf2baf..5070c2ad0fc 100644 --- a/applications/matter_weather_station/Kconfig +++ b/applications/matter_weather_station/Kconfig @@ -39,5 +39,5 @@ endif # NET_L2_OPENTHREAD source "${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.features" source "${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/config/nrfconnect/chip-module/Kconfig.defaults" -source "${ZEPHYR_BASE}/../nrf/samples/matter/common/src/Kconfig" +source "${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/src/Kconfig" source "Kconfig.zephyr" diff --git a/applications/matter_weather_station/Kconfig.sysbuild b/applications/matter_weather_station/Kconfig.sysbuild index 33ac7693c39..36d3e9c4363 100644 --- a/applications/matter_weather_station/Kconfig.sysbuild +++ b/applications/matter_weather_station/Kconfig.sysbuild @@ -5,13 +5,13 @@ # config NRF_DEFAULT_MULTIPROTOCOL - default y if ($(BOARD) = "thingy53_nrf5340_cpuapp") + default y if ("$(BOARD)" = "thingy53_nrf5340_cpuapp") choice BOOTLOADER default BOOTLOADER_MCUBOOT endchoice -if BOOTLOADER_MCUBOOT && ($(BOARD) = "thingy53_nrf5340_cpuapp") +if BOOTLOADER_MCUBOOT && ("$(BOARD)" = "thingy53_nrf5340_cpuapp") config MCUBOOT_UPDATEABLE_IMAGES default 2 diff --git a/applications/matter_weather_station/README.rst b/applications/matter_weather_station/README.rst index bb5832a7170..0056b869047 100644 --- a/applications/matter_weather_station/README.rst +++ b/applications/matter_weather_station/README.rst @@ -128,9 +128,9 @@ Matter weather station build types The Matter weather station application does not use a single :file:`prj.conf` file. Configuration files are provided for different build types, and they are located in the :file:`configuration/thingy53_nrf5340_cpuapp` directory. -Before you start testing the application, you can select one of the build types supported by the application, depending on the building method. +Before you start testing the application, you can select one of the build types supported by the application. -See :ref:`app_build_additions_build_types` and :ref:`modifying_build_types` for more information about this feature of the |NCS|. +See :ref:`app_build_additions_build_types` and :ref:`cmake_options` for more information. The application supports the following build types: @@ -142,18 +142,16 @@ The application supports the following build types: - File name - Supported board - Description - * - Debug + * - Debug (default) - :file:`prj.conf` - All from `Requirements`_ - - | Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs or command-line shell. - | Used by default if no build type is explicitly selected. + - Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs or command-line shell. * - Release - :file:`prj_release.conf` - All from `Requirements`_ - | Release version of the application; can be used to enable only the necessary application functionalities to optimize its performance. | - | .. note:: - | Currently, this application supports only the release build type when `Building for the nRF7002 Wi-Fi expansion board`_. + | Currently, this application supports only the release build type when `Building for the nRF7002 Wi-Fi expansion board`_. .. _matter_weather_station_app_build_configuration_overlays: @@ -168,6 +166,14 @@ The application comes with the following overlays: See `Generating factory data`_ to learn how to put factory data into device's storage. To learn more about factory data, read the :doc:`matter:nrfconnect_factory_data_configuration` page in the Matter documentation. + This overlay requires providing of the :file:`pm_static_factory_data.yml` Partition Manager static configuration file. + + To build the example with the factory data support, run the following command: + + .. code-block:: console + + west build -b thingy53_nrf5340_cpuapp -- -DEXTRA_CONF_FILE=overlay-factory_data.conf -DPM_STATIC_YML_FILE=pm_static_factory_data.yml + .. note:: Matter factory data support requires the dedicated partition layout. This means that if you build the application using the ``overlay-factory_data`` configuration overlay, it will not be compatible with other :ref:`Thingy:53 applications and samples `. @@ -182,8 +188,8 @@ Building and running Selecting a build type ====================== -Before you start testing the application, you can select one of the :ref:`matter_weather_station_app_build_types`, depending on your building method. -See :ref:`modifying_build_types` for detailed steps how to select a build type. +Before you start testing the application, you can select one of the :ref:`matter_weather_station_app_build_types`. +See :ref:`cmake_options` for information about how to select a build type. Building for the nRF7002 Wi-Fi expansion board ============================================== @@ -217,7 +223,7 @@ You can generate new factory data set when building for the target board by invo .. parsed-literal:: :class: highlight - west build -b thingy53_nrf5340_cpuapp -- -DOVERLAY_CONFIG=overlay-factory_data.conf + west build -b thingy53_nrf5340_cpuapp -- -DEXTRA_CONF_FILE=overlay-factory_data.conf This command builds the application with default certificates. After building the target, the generated :file:`factory_data.hex` file will be merged with the application target HEX file, so you can use the :ref:`regular command to flash it to the device `. @@ -313,7 +319,7 @@ The onboarding information representation depends on your commissioner setup. For this application, the data payload, which includes the device discriminator and setup PIN code, is encoded and shared using an NFC tag. When using the debug configuration, you can also get this type of information from the USB interface logs. -Alternatively, depending on your build type and selected configuration overlay, you can also use one of the following :ref:`onboarding information formats ` to provide the commissioner with the data required: +Alternatively, depending on your build type and selected overlay, you can also use one of the following :ref:`onboarding information formats ` to provide the commissioner with the data required: * For the debug and release build types: diff --git a/applications/matter_weather_station/VERSION b/applications/matter_weather_station/VERSION index 956d85eaac4..808984a04c5 100644 --- a/applications/matter_weather_station/VERSION +++ b/applications/matter_weather_station/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 2 -VERSION_MINOR = 5 -PATCHLEVEL = 0 +VERSION_MINOR = 6 +PATCHLEVEL = 99 VERSION_TWEAK = 0 EXTRAVERSION = diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/app.overlay b/applications/matter_weather_station/app.overlay similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/app.overlay rename to applications/matter_weather_station/app.overlay diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf b/applications/matter_weather_station/child_image/hci_ipc/prj.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj.conf rename to applications/matter_weather_station/child_image/hci_ipc/prj.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf b/applications/matter_weather_station/child_image/hci_ipc/prj_release.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf rename to applications/matter_weather_station/child_image/hci_ipc/prj_release.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/multiprotocol_rpmsg/prj.conf b/applications/matter_weather_station/child_image/multiprotocol_rpmsg/prj.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/multiprotocol_rpmsg/prj.conf rename to applications/matter_weather_station/child_image/multiprotocol_rpmsg/prj.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/multiprotocol_rpmsg/prj_release.conf b/applications/matter_weather_station/child_image/multiprotocol_rpmsg/prj_release.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/child_image/multiprotocol_rpmsg/prj_release.conf rename to applications/matter_weather_station/child_image/multiprotocol_rpmsg/prj_release.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/overlay-factory_data.conf b/applications/matter_weather_station/overlay-factory_data.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/overlay-factory_data.conf rename to applications/matter_weather_station/overlay-factory_data.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/pm_static_factory_data.yml b/applications/matter_weather_station/pm_static_factory_data.yml similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/pm_static_factory_data.yml rename to applications/matter_weather_station/pm_static_factory_data.yml diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/prj.conf b/applications/matter_weather_station/prj.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/prj.conf rename to applications/matter_weather_station/prj.conf diff --git a/applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/prj_release.conf b/applications/matter_weather_station/prj_release.conf similarity index 100% rename from applications/matter_weather_station/configuration/thingy53_nrf5340_cpuapp/prj_release.conf rename to applications/matter_weather_station/prj_release.conf diff --git a/applications/matter_weather_station/sample.yaml b/applications/matter_weather_station/sample.yaml index ab3a043793e..5442212e813 100644 --- a/applications/matter_weather_station/sample.yaml +++ b/applications/matter_weather_station/sample.yaml @@ -13,6 +13,7 @@ tests: applications.matter_weather_station.debug: build_only: true extra_args: OVERLAY_CONFIG=overlay-factory_data.conf + PM_STATIC_YML_FILE=${CMAKE_CURRENT_SOURCE_DIR}/pm_static_factory_data.yml platform_allow: thingy53_nrf5340_cpuapp platform_exclude: thingy53_nrf5340_cpuapp_ns integration_platforms: @@ -20,6 +21,7 @@ tests: applications.matter_weather_station.release: build_only: true extra_args: OVERLAY_CONFIG=overlay-factory_data.conf CONF_FILE=prj_release.conf + PM_STATIC_YML_FILE=${CMAKE_CURRENT_SOURCE_DIR}/pm_static_factory_data.yml platform_allow: thingy53_nrf5340_cpuapp platform_exclude: thingy53_nrf5340_cpuapp_ns integration_platforms: diff --git a/applications/matter_weather_station/src/app_task.cpp b/applications/matter_weather_station/src/app_task.cpp index 9cb9c43dfc3..7f65bb512fa 100644 --- a/applications/matter_weather_station/src/app_task.cpp +++ b/applications/matter_weather_station/src/app_task.cpp @@ -9,10 +9,10 @@ #include "battery.h" #include "buzzer.h" +#include "app/matter_init.h" +#include "app/task_executor.h" #include "board/board.h" -#include "init/matter_init.h" -#include "led/led_widget.h" -#include "tasks/task_executor.h" +#include "board/led_widget.h" #ifdef CONFIG_CHIP_OTA_REQUESTOR #include "dfu/ota/ota_util.h" @@ -22,10 +22,8 @@ #include "dfu/smp/dfu_over_smp.h" #endif -#include #include #include -#include #include #include @@ -90,31 +88,6 @@ Identify sIdentifyHumidity = { chip::EndpointId{ kHumidityMeasurementEndpointId Identify sIdentifyPressure = { chip::EndpointId{ kPressureMeasurementEndpointId }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop, Clusters::Identify::IdentifyTypeEnum::kAudibleBeep }; -/* NOTE! This key is for test/certification only and should not be available in production devices! - * If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data. - */ -uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, - 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, - 0xcc, 0xdd, 0xee, 0xff }; -chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; - -OTATestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; -CommonCaseDeviceServerInitParams sServerInitParams{}; - -#ifdef CONFIG_CHIP_FACTORY_DATA -CHIP_ERROR CustomFactoryDataInit() -{ - MutableByteSpan enableKey(sTestEventTriggerEnableKey); - auto *factoryDataProvider = Nordic::Matter::GetFactoryDataProvider(); - VerifyOrReturnError(factoryDataProvider, CHIP_ERROR_INTERNAL); - CHIP_ERROR err = factoryDataProvider->GetEnableKey(enableKey); - if (err != CHIP_NO_ERROR) { - LOG_ERR("FactoryDataProvider::GetEnableKey() failed. Could not delegate a test event trigger"); - memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey)); - } - return CHIP_NO_ERROR; -} -#endif } /* namespace */ void AppTask::MeasurementsTimerHandler() @@ -124,7 +97,8 @@ void AppTask::MeasurementsTimerHandler() void AppTask::OnIdentifyStart(Identify *) { - TaskExecutor::PostTask([] { GetBoard().GetLED(DeviceLeds::LED2).Blink(LedConsts::kIdentifyBlinkRate_ms); }); + Nrf::PostTask( + [] { Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2).Blink(Nrf::LedConsts::kIdentifyBlinkRate_ms); }); k_timer_start(&sIdentifyTimer, K_MSEC(kIdentifyTimerIntervalMs), K_MSEC(kIdentifyTimerIntervalMs)); } @@ -320,82 +294,34 @@ void AppTask::UpdateClustersState() UpdatePowerSourceClusterState(); } -void AppTask::MatterEventHandler(const ChipDeviceEvent *event, intptr_t /* arg */) -{ - bool isNetworkProvisioned = false; - - switch (event->Type) { - case DeviceEventType::kCHIPoBLEAdvertisingChange: -#ifdef CONFIG_CHIP_NFC_COMMISSIONING - if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started) { - if (NFCMgr().IsTagEmulationStarted()) { - LOG_INF("NFC Tag emulation is already started"); - } else { - ShareQRCodeOverNFC( - chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - } - } else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped) { - NFCMgr().StopTagEmulation(); - } -#endif - if (ConnectivityMgr().NumBLEConnections() != 0) { - GetBoard().UpdateDeviceState(DeviceState::DeviceConnectedBLE); - } else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started) { - GetBoard().UpdateDeviceState(DeviceState::DeviceAdvertisingBLE); - } else { - GetBoard().UpdateDeviceState(DeviceState::DeviceDisconnected); - } - break; -#if defined(CONFIG_NET_L2_OPENTHREAD) - case DeviceEventType::kDnssdInitialized: -#if CONFIG_CHIP_OTA_REQUESTOR - InitBasicOTARequestor(); -#endif /* CONFIG_CHIP_OTA_REQUESTOR */ - break; - case DeviceEventType::kThreadStateChange: - isNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned() && ConnectivityMgr().IsThreadEnabled(); -#elif defined(CONFIG_CHIP_WIFI) - case DeviceEventType::kWiFiConnectivityChange: - isNetworkProvisioned = - ConnectivityMgr().IsWiFiStationProvisioned() && ConnectivityMgr().IsWiFiStationEnabled(); -#if CONFIG_CHIP_OTA_REQUESTOR - if (event->WiFiConnectivityChange.Result == kConnectivity_Established) { - InitBasicOTARequestor(); - } -#endif /* CONFIG_CHIP_OTA_REQUESTOR */ -#endif - if (isNetworkProvisioned) { - GetBoard().UpdateDeviceState(DeviceState::DeviceProvisioned); - } - break; - default: - break; - } -} - void AppTask::UpdateLedState() { if (!Instance().mGreenLED || !Instance().mBlueLED || !Instance().mRedLED) { return; } - switch (GetBoard().GetDeviceState()) { - case DeviceState::DeviceAdvertisingBLE: - Instance().mBlueLED->Blink(LedConsts::StatusLed::Disconnected::kOn_ms, - LedConsts::StatusLed::Disconnected::kOff_ms); - case DeviceState::DeviceDisconnected: - Instance().mGreenLED->Blink(LedConsts::StatusLed::Disconnected::kOn_ms, - LedConsts::StatusLed::Disconnected::kOff_ms); + Instance().mGreenLED->Set(false); + Instance().mBlueLED->Set(false); + Instance().mRedLED->Set(false); + + switch (Nrf::GetBoard().GetDeviceState()) { + case Nrf::DeviceState::DeviceAdvertisingBLE: + Instance().mBlueLED->Blink(Nrf::LedConsts::StatusLed::Disconnected::kOn_ms, + Nrf::LedConsts::StatusLed::Disconnected::kOff_ms); + break; + case Nrf::DeviceState::DeviceDisconnected: + Instance().mGreenLED->Blink(Nrf::LedConsts::StatusLed::Disconnected::kOn_ms, + Nrf::LedConsts::StatusLed::Disconnected::kOff_ms); break; - case DeviceState::DeviceConnectedBLE: - Instance().mBlueLED->Blink(LedConsts::StatusLed::BleConnected::kOn_ms, - LedConsts::StatusLed::BleConnected::kOff_ms); + case Nrf::DeviceState::DeviceConnectedBLE: + Instance().mBlueLED->Blink(Nrf::LedConsts::StatusLed::BleConnected::kOn_ms, + Nrf::LedConsts::StatusLed::BleConnected::kOff_ms); break; - case DeviceState::DeviceProvisioned: - Instance().mRedLED->Blink(LedConsts::StatusLed::Disconnected::kOn_ms, - LedConsts::StatusLed::Disconnected::kOff_ms); - Instance().mBlueLED->Blink(LedConsts::StatusLed::Disconnected::kOn_ms, - LedConsts::StatusLed::Disconnected::kOff_ms); + case Nrf::DeviceState::DeviceProvisioned: + Instance().mRedLED->Blink(Nrf::LedConsts::StatusLed::Disconnected::kOn_ms, + Nrf::LedConsts::StatusLed::Disconnected::kOff_ms); + Instance().mBlueLED->Blink(Nrf::LedConsts::StatusLed::Disconnected::kOn_ms, + Nrf::LedConsts::StatusLed::Disconnected::kOff_ms); break; default: break; @@ -405,23 +331,30 @@ void AppTask::UpdateLedState() CHIP_ERROR AppTask::Init() { /* Initialize Matter stack */ - sServerInitParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; - Nordic::Matter::InitData initConfig{ .mServerInitParams = &sServerInitParams }; -#ifdef CONFIG_CHIP_FACTORY_DATA - initConfig.mPostServerInitClbk = CustomFactoryDataInit; +#ifdef CONFIG_MCUMGR_TRANSPORT_BT + ReturnErrorOnFailure( + Nrf::Matter::PrepareServer(Nrf::Matter::InitData{ .mPostServerInitClbk = []() -> CHIP_ERROR { + Nrf::GetDFUOverSMP().StartServer(); + return CHIP_NO_ERROR; + } })); +#else + ReturnErrorOnFailure(Nrf::Matter::PrepareServer()); #endif - ReturnErrorOnFailure(Nordic::Matter::PrepareServer(MatterEventHandler, initConfig)); /* Set references for RGB LED */ - mRedLED = &GetBoard().GetLED(DeviceLeds::LED1); - mGreenLED = &GetBoard().GetLED(DeviceLeds::LED2); - mBlueLED = &GetBoard().GetLED(DeviceLeds::LED3); + mRedLED = &Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED1); + mGreenLED = &Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED2); + mBlueLED = &Nrf::GetBoard().GetLED(Nrf::DeviceLeds::LED3); - if (!GetBoard().Init(nullptr, UpdateLedState)) { + if (!Nrf::GetBoard().Init(nullptr, UpdateLedState)) { LOG_ERR("User interface initialization failed."); return CHIP_ERROR_INCORRECT_STATE; } + /* Register Matter event handler that controls the connectivity status LED based on the captured Matter network + * state. */ + ReturnErrorOnFailure(Nrf::Matter::RegisterEventHandler(Nrf::Board::DefaultMatterEventHandler, 0)); + if (!device_is_ready(sBme688SensorDev)) { LOG_ERR("BME688 sensor device not ready"); return chip::System::MapErrorZephyr(-ENODEV); @@ -453,17 +386,12 @@ CHIP_ERROR AppTask::Init() /* Initialize timers */ k_timer_init( - &sMeasurementsTimer, [](k_timer *) { TaskExecutor::PostTask([] { MeasurementsTimerHandler(); }); }, - nullptr); + &sMeasurementsTimer, [](k_timer *) { Nrf::PostTask([] { MeasurementsTimerHandler(); }); }, nullptr); k_timer_init( - &sIdentifyTimer, [](k_timer *) { TaskExecutor::PostTask([] { IdentifyTimerHandler(); }); }, nullptr); + &sIdentifyTimer, [](k_timer *) { Nrf::PostTask([] { IdentifyTimerHandler(); }); }, nullptr); k_timer_start(&sMeasurementsTimer, K_MSEC(kMeasurementsIntervalMs), K_MSEC(kMeasurementsIntervalMs)); -#ifdef CONFIG_MCUMGR_TRANSPORT_BT - GetDFUOverSMP().StartServer(); -#endif - - return Nordic::Matter::StartServer(); + return Nrf::Matter::StartServer(); } CHIP_ERROR AppTask::StartApp() @@ -471,7 +399,7 @@ CHIP_ERROR AppTask::StartApp() ReturnErrorOnFailure(Init()); while (true) { - TaskExecutor::DispatchNextTask(); + Nrf::DispatchNextTask(); } return CHIP_NO_ERROR; diff --git a/applications/matter_weather_station/src/app_task.h b/applications/matter_weather_station/src/app_task.h index b23e91c47ea..a1e8f442da9 100644 --- a/applications/matter_weather_station/src/app_task.h +++ b/applications/matter_weather_station/src/app_task.h @@ -6,7 +6,7 @@ #pragma once -#include "led/led_widget.h" +#include "board/led_widget.h" #include #include @@ -36,9 +36,8 @@ class AppTask { static void MeasurementsTimerHandler(); static void IdentifyTimerHandler(); - static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t arg); - LEDWidget *mRedLED; - LEDWidget *mGreenLED; - LEDWidget *mBlueLED; + Nrf::LEDWidget *mRedLED; + Nrf::LEDWidget *mGreenLED; + Nrf::LEDWidget *mBlueLED; }; diff --git a/applications/matter_weather_station/src/chip_project_config.h b/applications/matter_weather_station/src/chip_project_config.h index cb103b88b95..56fb9ae7180 100644 --- a/applications/matter_weather_station/src/chip_project_config.h +++ b/applications/matter_weather_station/src/chip_project_config.h @@ -38,16 +38,4 @@ 0x39, 0xa0, 0xf7, 0xb4, 0x86, 0x10, 0x32, 0x33, 0x01, 0xc2, 0xe4, 0x0f, \ 0xe0, 0x4b, 0x9c, 0x2d, 0x4d, 0x41, 0x13, 0xfd, 0xc3, 0x11, 0xe1, 0x00, \ 0x34, 0xa4, 0xe1, 0x7c, 0x09, 0x27, 0x45, 0x7b }; -#else -/* Use a default pairing code if one hasn't been provisioned in flash. */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -/* Configure device configuration with exemplary data */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "Nordic" -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "WeatherStation" -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION_STRING "Prerelease weather station device" -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION 1 -#define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING "Prerelease weather station firmware" -#define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION 1 #endif diff --git a/applications/matter_weather_station/sysbuild.cmake b/applications/matter_weather_station/sysbuild.cmake deleted file mode 100644 index 8970053e590..00000000000 --- a/applications/matter_weather_station/sysbuild.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -if("${OVERLAY_CONFIG}" STREQUAL "overlay-factory_data.conf") - set(PM_STATIC_YML_FILE ${APPLICATION_CONFIG_DIR}/pm_static_factory_data.yml PARENT_SCOPE) -endif() diff --git a/applications/nrf5340_audio/CMakeLists.txt b/applications/nrf5340_audio/CMakeLists.txt index 7739f0c0cba..929b1f3bf1c 100644 --- a/applications/nrf5340_audio/CMakeLists.txt +++ b/applications/nrf5340_audio/CMakeLists.txt @@ -27,22 +27,6 @@ if(CONFIG_AUDIO_DFU EQUAL 2) set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_LIST_DIR}/dfu/conf/pm_dfu_external_flash.yml) endif() -if ((CONFIG_AUDIO_DFU EQUAL 1) OR (CONFIG_AUDIO_DFU EQUAL 2)) - list(APPEND empty_net_core_OVERLAY_CONFIG - "${CMAKE_CURRENT_LIST_DIR}/dfu/conf/overlay-empty_net_core.conf" - ) - - # Disable pretick anomaly workaround. The workaround causes a resource conflict between B0N and - # the controller, and as the controller does not use RTC to wake up from sleep it is not - # affected by the anomaly. - list(APPEND empty_net_core_b0n_CONFIG_SOC_NRF53_RTC_PRETICK n) - - if (CONFIG_B0N_MINIMAL) - set(min_b0n_flag "-m") - list(APPEND empty_net_core_b0n_OVERLAY_CONFIG overlay-minimal-size.conf) - endif() -endif() - # Flag which defines whether application is compiled as gateway/dongle or headset add_compile_definitions(HEADSET=1) add_compile_definitions(GATEWAY=2) @@ -60,10 +44,27 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/utils/fw_info_app.c.in" # Target sources below are specific to the nRF5340 Audio DK HW target_sources(app PRIVATE - src/main.c + src/nrf5340_audio_common.c ${CMAKE_BINARY_DIR}/fw_info_app.c ) +if (CONFIG_BT_BAP_BROADCAST_SINK) + add_subdirectory(broadcast_sink) +endif() + +if (CONFIG_BT_BAP_BROADCAST_SOURCE) + add_subdirectory(broadcast_source) +endif() + +if (CONFIG_BT_BAP_UNICAST_CLIENT) + add_subdirectory(unicast_client) +endif() + +if (CONFIG_BT_BAP_UNICAST_SERVER) + add_subdirectory(unicast_server) +endif() + + # Include application events and configuration headers zephyr_library_include_directories( include @@ -93,22 +94,3 @@ if (CONFIG_HW_CODEC_CIRRUS_LOGIC) message(FATAL_ERROR "Cirrus Logic/sdk-mcu-drivers repository not found\n") endif() endif() - -if ((CONFIG_AUDIO_DFU EQUAL 1) OR (CONFIG_AUDIO_DFU EQUAL 2)) - set(BLE5_CTR_SIGN_STEP ${APPLICATION_BINARY_DIR}/dummy) - file(TO_CMAKE_PATH ${ZEPHYR_NRF_MODULE_DIR}/lib/bin/bt_ll_acs_nrf53/bin CMAKE_STYLE_LL_ACS_NRF53_BIN) - - add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/tools/buildprog/ble5-ctr-rpmsg_sign.py - -I ${CMAKE_STYLE_LL_ACS_NRF53_BIN} -b ${APPLICATION_BINARY_DIR} ${min_b0n_flag} - OUTPUT ${BLE5_CTR_SIGN_STEP} - DEPENDS merged_domains_hex - COMMENT "Running post-build ble5-ctr signing step..." - ) - - add_custom_target( - post_bin ALL - DEPENDS - ${BLE5_CTR_SIGN_STEP} - ) -endif() diff --git a/applications/nrf5340_audio/Kconfig b/applications/nrf5340_audio/Kconfig index f0d8f1d396a..32f201bf930 100644 --- a/applications/nrf5340_audio/Kconfig +++ b/applications/nrf5340_audio/Kconfig @@ -33,6 +33,24 @@ config TRANSPORT_CIS endchoice #----------------------------------------------------------------------------# +if (TRANSPORT_BIS && AUDIO_DEV = 1) +rsource "broadcast_sink/Kconfig.defaults" +endif # TRANSPORT_BIS && AUDIO_DEV = 1 + +if (TRANSPORT_BIS && AUDIO_DEV = 2) +rsource "broadcast_source/Kconfig.defaults" +endif # TRANSPORT_BIS && AUDIO_DEV = 2 + +if (TRANSPORT_CIS && AUDIO_DEV = 1) +rsource "unicast_server/Kconfig.defaults" +endif # TRANSPORT_CIS && AUDIO_DEV = 1 + +if (TRANSPORT_CIS && AUDIO_DEV = 2) +rsource "unicast_client/Kconfig.defaults" +endif # TRANSPORT_CIS && AUDIO_DEV = 2 + + + rsource "Kconfig.defaults" rsource "src/audio/Kconfig" rsource "src/bluetooth/Kconfig" @@ -48,6 +66,10 @@ module = MAIN module-str = main source "subsys/logging/Kconfig.template.log_config" +module = NRF5340_AUDIO_COMMON +module-str = nrf5340_audio_common +source "subsys/logging/Kconfig.template.log_config" + config PRINT_STACK_USAGE_MS depends on THREAD_ANALYZER && INIT_STACKS int "Print stack usage every x milliseconds" diff --git a/applications/nrf5340_audio/Kconfig.defaults b/applications/nrf5340_audio/Kconfig.defaults index afc72c0803b..ca2babba816 100644 --- a/applications/nrf5340_audio/Kconfig.defaults +++ b/applications/nrf5340_audio/Kconfig.defaults @@ -22,7 +22,7 @@ config THREAD_NAME default y config NCS_INCLUDE_RPMSG_CHILD_IMAGE - default !BT_LL_ACS_NRF53 + default y # Workaround to not use fatal_error.c in NCS. Note that the system may still # reset on error depending on the build configuraion @@ -45,9 +45,6 @@ config BOARD_ENABLE_DCDC_NET config BOARD_ENABLE_CPUNET default y -config NFCT_PINS_AS_GPIOS - default y - config ZBUS default y @@ -72,9 +69,6 @@ config NRFX_I2S0 config PCM_MIX default y -config TONE - default y - config PSCM default y @@ -146,9 +140,6 @@ config FS_FATFS_EXFAT config FS_FATFS_MAX_LFN default 255 -config BT_LL_ACS_NRF53 - default y - config WATCHDOG default y diff --git a/applications/nrf5340_audio/README.rst b/applications/nrf5340_audio/README.rst deleted file mode 100644 index 1fc48bb75d5..00000000000 --- a/applications/nrf5340_audio/README.rst +++ /dev/null @@ -1,861 +0,0 @@ -.. _nrf53_audio_app_description: - -nRF5340 Audio configuration and testing -####################################### - -.. contents:: - :local: - :depth: 2 - -The nRF5340 Audio application has the following unique characteristics: - -* It is developed for use only with the :ref:`nRF5340 Audio development kit `. -* In its default configuration, the application requires the :ref:`LC3 software codec `. -* The application also comes with various application-specific tools, including the :file:`buildprog.py` Python script that simplifies building and programming the firmware. -* The application uses the :ref:`lib_bt_ll_acs_nrf53_readme` as the controller programmed to the network core. - This controller is required in all application configurations and testing scenarios. - -.. _nrf53_audio_app_requirements: - -Requirements -************ - -The nRF5340 Audio application is designed to be used only with the following hardware: - -.. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf5340_audio_dk_nrf5340 - -.. note:: - The application supports PCA10121 revisions 1.0.0 or above. - The application is also compatible with the following pre-launch revisions: - - * Revisions 0.8.0 and above. - -You need at least two nRF5340 Audio development kits (one with the gateway firmware and one with headset firmware) to test the application. -For CIS with TWS in mind, three kits are required. - -.. _nrf53_audio_app_requirements_codec: - -Software codec requirements -=========================== - -The nRF5340 Audio application only supports the :ref:`LC3 software codec `, developed specifically for use with LE Audio. - -.. _nrf53_audio_app_dk: -.. _nrf53_audio_app_dk_features: - -nRF5340 Audio development kit -============================= - -The nRF5340 Audio development kit is a hardware development platform that demonstrates the nRF5340 Audio application. -Read the `nRF5340 Audio DK Hardware`_ documentation on Nordic Semiconductor Infocenter for more information about this development kit. - -.. _nrf53_audio_app_configuration_files: - -nRF5340 Audio configuration files -================================= - -The nRF5340 Audio application uses :file:`Kconfig.defaults` files to change configuration defaults automatically, based on the different application versions and device types. - -Only one of the following :file:`.conf` files is included when building: - -* :file:`prj.conf` is the default configuration file and it implements the debug application version. -* :file:`prj_release.conf` is the optional configuration file and it implements the release application version. - No debug features are enabled in the release application version. - When building using the command line, you must explicitly specify if :file:`prj_release.conf` is going to be included instead of :file:`prj.conf`. - See :ref:`nrf53_audio_app_building` for details. - -In addition, the application features the :file:`child_image` directory with an experimental :file:`hci_ipc.conf`. -This file is a work-in-progress implementation of the SoftDevice Controller that has not been thoroughly tested and should not be used. -The application is only tested using :ref:`lib_bt_ll_acs_nrf53_readme`. - -Requirements for FOTA -===================== - -To test Firmware Over-The-Air (FOTA), you need an Android or iOS device with the `nRF Connect Device Manager`_ app installed. - -If you want to do FOTA upgrades for the application core and the network core at the same time, you need an external flash shield. -See :ref:`nrf53_audio_app_configuration_configure_fota` for more details. - -.. _nrf53_audio_app_ui: - -User interface -************** - -The application implements a simple user interface based on the available PCB elements. -You can control the application using predefined switches and buttons while the LEDs display information. - -.. _nrf53_audio_app_ui_switches: - -Switches -======== - -The application uses the following switches on the supported development kit: - -+-------------------+-------------------------------------------------------------------------------------+ -| Switch | Function | -+===================+=====================================================================================+ -| **POWER** | Turns the development kit on or off. | -+-------------------+-------------------------------------------------------------------------------------+ -| **DEBUG ENABLE** | Turns on or off power for debug features. | -| | This switch is used for accurate power and current measurements. | -+-------------------+-------------------------------------------------------------------------------------+ - -.. _nrf53_audio_app_ui_buttons: - -Buttons -======= - -The application uses the following buttons on the supported development kit: - -+---------------+-----------------------------------------------------------------------------------------------------------+ -| Button | Function | -+===============+===========================================================================================================+ -| **VOL-** | Depending on the moment it is pressed: | -| | | -| | * Long-pressed during startup: Changes the headset to the left channel one. | -| | * Pressed on the headset or the CIS gateway during playback: Turns the playback volume down (and unmutes).| -+---------------+-----------------------------------------------------------------------------------------------------------+ -| **VOL+** | Depending on the moment it is pressed: | -| | | -| | * Long-pressed during startup: Changes the headset to the right channel one. | -| | * Pressed on the headset or the CIS gateway during playback: Turns the playback volume up (and unmutes). | -+---------------+-----------------------------------------------------------------------------------------------------------+ -| **PLAY/PAUSE**| Starts or pauses the playback. | -+---------------+-----------------------------------------------------------------------------------------------------------+ -| **BTN 4** | Depending on the moment it is pressed: | -| | | -| | * Long-pressed during startup: Turns on the DFU mode, if | -| | the device is :ref:`configured for it`. | -| | * Pressed on the gateway during playback: Sends a test tone generated on the device. | -| | Use this tone to check the synchronization of headsets. | -| | * Pressed on the gateway during playback multiple times: Changes the tone frequency. | -| | The available values are 1000 Hz, 2000 Hz, and 4000 Hz. | -| | * Pressed on a BIS headset during playback: Change audio stream, if more than one is | -| | available. | -+---------------+-----------------------------------------------------------------------------------------------------------+ -| **BTN 5** | Depending on the moment it is pressed: | -| | | -| | * Long-pressed during startup: Clears the previously stored bonding information. | -| | * Pressed during playback: Mutes the playback volume. | -| | * Pressed on a BIS headset during playback: Change the gateway, if more than one is | -| | available. | -+---------------+-----------------------------------------------------------------------------------------------------------+ -| **RESET** | Resets the device to the originally programmed settings. | -| | This reverts any changes made during testing, for example the channel switches with **VOL** buttons. | -+---------------+-----------------------------------------------------------------------------------------------------------+ - -.. _nrf53_audio_app_ui_leds: - -LEDs -==== - -To indicate the tasks performed, the application uses the LED behavior described in the following table: - -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| LED |Indication | -+==========================+===========================================================================================================+ -| **LED1** | Off - No Bluetooth connection. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Blinking blue - Depending on the device and the mode: | -| | | -| | * Headset: Kits have started streaming audio (BIS and CIS modes). | -| | * Gateway: Kit has connected to a headset (CIS mode) or has started broadcasting audio (BIS mode). | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid blue - Headset, depending on the mode: | -| | Kits have connected to the gateway (CIS mode) or found a broadcasting stream (BIS mode). | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **LED2** | Off - Sync not achieved. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid green - Sync achieved (both drift and presentation compensation are in the ``LOCKED`` state). | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **LED3** | Blinking green - The nRF5340 Audio DK application core is running. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **CODEC** | Off - No configuration loaded to the onboard hardware codec. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid green - Hardware codec configuration loaded. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **RGB1** | Solid green - The device is programmed as the gateway. | -| (bottom side LEDs around +-----------------------------------------------------------------------------------------------------------+ -| the center opening) | Solid blue - The device is programmed as the left headset. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid magenta - The device is programmed as the right headset. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid yellow - The device is programmed with factory firmware. | -| | It must be re-programmed as gateway or headset. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid red (debug mode) - Fault in the application core has occurred. | -| | See UART log for details and use the **RESET** button to reset the device. | -| | In the release mode, the device resets automatically with no indication on LED or UART. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **RGB 2** | Controlled by the Bluetooth LE Controller on the network core. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Blinking green - Ongoing CPU activity. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid red - Error. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid white (all colors on) - The **RGB 2** LED is not initialized by the Bluetooth LE Controller. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **ERR** | PMIC error or a charging error (or both). | -| | Also turns on when charging the battery exceeds seven hours, since the PMIC has a protection timeout, | -| | which stops the charging. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **CHG** | Off - Charge completed or no battery connected. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid yellow - Charging in progress. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **OB/EXT** | Off - No 3.3 V power available. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid green - On-board hardware codec selected. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Solid yellow - External hardware codec selected. | -| | This LED turns solid yellow also when the devices are reset, for the time then pins are floating. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **FTDI SPI** | Off - No data is written to the hardware codec using SPI. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Yellow - The same SPI is used for both the hardware codec and the SD card. | -| | When this LED is yellow, the shared SPI is used by the FTDI to write data to the hardware codec. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **IFMCU** | Off - No PC connection available. | -| (bottom side) +-----------------------------------------------------------------------------------------------------------+ -| | Solid green - Connected to PC. | -| +-----------------------------------------------------------------------------------------------------------+ -| | Rapid green flash - USB enumeration failed. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ -| **HUB** | Off - No PC connection available. | -| (bottom side) +-----------------------------------------------------------------------------------------------------------+ -| | Green - Standard USB hub operation. | -+--------------------------+-----------------------------------------------------------------------------------------------------------+ - -.. _nrf53_audio_app_configuration: - -Configuration -************* - -|config| - -.. _nrf53_audio_app_configuration_select_bis: - -Selecting the BIS mode -====================== - -The CIS mode is the default operating mode for the application. -To switch to the BIS mode, set the :ref:`CONFIG_TRANSPORT_BIS ` Kconfig option to ``y`` in the :file:`prj.conf` file for the debug version and in the :file:`prj_release.conf` file for the release version. - -Enabling the BIS mode with two gateways ---------------------------------------- - -In addition to the standard BIS mode with one gateway, you can also add a second gateway device that the BIS headsets can receive audio stream from. -To configure the second gateway, add both the :ref:`CONFIG_TRANSPORT_BIS ` and the :ref:`CONFIG_BT_AUDIO_USE_BROADCAST_NAME_ALT ` Kconfig options set to ``y`` to the :file:`prj.conf` file for the debug version and to the :file:`prj_release.conf` file for the release version. -You can provide an alternative name to the second gateway using the :ref:`CONFIG_BT_AUDIO_BROADCAST_NAME_ALT ` or use the default alternative name. - -You build each BIS gateway separately using the normal procedures from :ref:`nrf53_audio_app_building`. -After building the first gateway, configure the required Kconfig options for the second gateway and build the second gateway firmware. -Remember to program the two firmware versions to two separate gateway devices. - -.. _nrf53_audio_app_configuration_select_bidirectional: - -Selecting the CIS bidirectional communication -============================================= - -The CIS unidirectional mode is the default operating mode for the application. -To switch to the bidirectional mode, set the :ref:`CONFIG_STREAM_BIDIRECTIONAL ` Kconfig option to ``y`` in the :file:`prj.conf` file (for the debug version) or in the :file:`prj_release.conf` file (for the release version). - -.. _nrf53_audio_app_configuration_enable_walkie_talkie: - -Enabling the walkie-talkie demo -------------------------------- - -The walkie-talkie demo uses one or two bidirectional streams from the gateway to one or two headsets. -The PDM microphone is used as input on both the gateway and headset device. -To switch to using the walkie-talkie, set the :ref:`CONFIG_WALKIE_TALKIE_DEMO ` Kconfig option to ``y`` in the :file:`prj.conf` file (for the debug version) or in the :file:`prj_release.conf` file (for the release version). - -.. _nrf53_audio_app_configuration_select_i2s: - -Selecting the I2S serial -======================== - -In the default configuration, the gateway application uses the USB serial port as the audio source. -The :ref:`nrf53_audio_app_building` and :ref:`nrf53_audio_app_testing` steps also refer to using the USB serial connection. - -To switch to using the I2S serial connection, set the :ref:`CONFIG_AUDIO_SOURCE_I2S ` Kconfig option to ``y`` in the :file:`prj.conf` file for the debug version and in the :file:`prj_release.conf` file for the release version. - -When testing the application, an additional audio jack cable is required to use I2S. -Use this cable to connect the audio source (PC) to the analog **LINE IN** on the development kit. - -.. _nrf53_audio_app_configuration_configure_fota: - -Configuring FOTA upgrades -========================= - -.. caution:: - Firmware based on the |NCS| versions earlier than v2.1.0 does not support DFU. - FOTA is not available for those versions. - - You can test performing separate application and network core upgrades, but for production, both cores must be updated at the same time. - When updates take place in the inter-core communication module (HCI RPMsg), communication between the cores will break if they are not updated together. - -You can configure Firmware Over-The-Air (FOTA) upgrades to replace the applications on both the application core and the network core. -The nRF5340 Audio application supports the following types of DFU flash memory layouts: - -* Internal flash memory layout - which supports only single-image DFU. -* External flash memory layout - which supports :ref:`multi-image DFU `. - -The LE Audio Controller Subsystem for nRF53 supports both the normal and minimal sizes of the bootloader. -The minimal size is specified using the :kconfig:option:`CONFIG_NETBOOT_MIN_PARTITION_SIZE`. - -Hardware requirements for external flash memory DFU ---------------------------------------------------- - -To enable the external flash DFU, you need an additional flash memory shield. -See `Requirements for external flash memory DFU`_ in the nRF5340 Audio DK Hardware documentation in Infocenter for more information. - -Enabling FOTA upgrades ----------------------- - -The FOTA upgrades are only available when :ref:`nrf53_audio_app_building_script`. -With the appropriate parameters provided, the :file:`buildprog.py` Python script will add overlay files for the given DFU type. -To enable the desired FOTA functions: - -* To define flash memory layout, include the ``-m internal`` parameter for the internal layout (when using the ``release`` application version) or the ``-m external`` parameter for the external layout (when using either ``release`` or ``debug``). -* To use the minimal size network core bootloader, add the ``-M`` parameter. - -For the full list of parameters and examples, see the :ref:`nrf53_audio_app_building_script_running` section. - -FOTA build files ----------------- - -The generated FOTA build files use the following naming patterns: - -* For multi-image DFU, the file is called ``dfu_application.zip``. - This file updates two cores with one single file. -* For single-image DFU, the bin file for the application core is called ``app_update.bin``. - The bin file for the network core is called ``net_core_app_update.bin``. - In this scenario, the cores are updated one by one with two separate files in two actions. - -See :ref:`app_build_output_files` for more information about the image files. - -.. note:: - |nrf5340_audio_net_core_hex_note| - -Entering the DFU mode ---------------------- - -The |NCS| uses :ref:`SMP server and mcumgr ` as the DFU backend. -Unlike the CIS and BIS modes for gateway and headsets, the DFU mode is advertising using the SMP server service. -For this reason, to enter the DFU mode, you must long press **BTN 4** during each device startup to have the nRF5340 Audio DK enter the DFU mode. - -To identify the devices before the DFU takes place, the DFU mode advertising names mention the device type directly. -The names follow the pattern in which the device *ROLE* is inserted before the ``_DFU`` suffix. -For example: - -* Gateway: NRF5340_AUDIO_GW_DFU -* Left Headset: NRF5340_AUDIO_HL_DFU -* Right Headset: NRF5340_AUDIO_HR_DFU - -The first part of these names is based on :kconfig:option:`CONFIG_BT_DEVICE_NAME`. - -.. note:: - When performing DFU for the nRF5340 Audio application, there will be one or more error prints related to opening flash area ID 1. - This is due to restrictions in the DFU system, and the error print is expected. - The DFU process should still complete successfully. - -.. _nrf53_audio_app_building: - -Building and running -******************** - -This sample can be found under :file:`applications/nrf5340_audio` in the nRF Connect SDK folder structure. - -.. note:: - Building and programming the nRF5340 Audio application is different from the :ref:`standard procedure ` of building and programming for the nRF5340 DK. - This is because the nRF5340 Audio application only builds and programs the files for the application core. - |nrf5340_audio_net_core_hex_note| - -You can build and program the application in one of the following ways: - -* :ref:`nrf53_audio_app_building_script`. - This is the suggested method. - Using this method allows you to build and program multiple development kits at the same time. -* :ref:`nrf53_audio_app_building_standard`. - Using this method requires building and programming each development kit separately. - -.. important:: - Building and programming using the |nRFVSC| is currently not supported. - -.. note:: - You might want to check the :ref:`nRF5340 Audio application known issues ` before building and programming the application. - -Testing out of the box -====================== - -Each development kit comes preprogrammed with basic firmware that indicates if the kit is functional. -Before building the application, you can verify if the kit is working by completing the following steps: - -1. Plug the device into the USB port. -#. Turn on the development kit using the On/Off switch. -#. Observe **RGB1** (bottom side LEDs around the center opening that illuminate the Nordic Semiconductor logo) turn solid yellow, **OB/EXT** turn solid green, and **LED3** start blinking green. - -You can now program the development kits with either gateway or headset firmware before they can be used. - -.. _nrf53_audio_app_adding_FEM_support: - -Adding FEM support -================== - -You can add support for the nRF21540 front-end module (FEM) to this application by using one of the following options, depending on how you decide to build the application: - -* If you opt for :ref:`nrf53_audio_app_building_script`, add the ``--nrf21540`` to the script's building command. -* If you opt for :ref:`nrf53_audio_app_building_standard`, add the ``-DSHIELD=nrf21540ek_fwd`` to the ``west build`` command. - For example: - - .. code-block:: console - - west build -b nrf5340_audio_dk_nrf5340_cpuapp --pristine -- -DCONFIG_AUDIO_DEV=1 -DSHIELD=nrf21540ek_fwd -DCONF_FILE=prj_release.conf - -To set the TX power output, use the :ref:`CONFIG_NRF_21540_MAIN_TX_POWER ` and :ref:`CONFIG_NRF_21540_PRI_ADV_TX_POWER ` Kconfig options. - -.. note:: - When you build the nRF5340 Audio application with the nRF21540 FEM support, the :ref:`lib_bt_ll_acs_nrf53_readme` does not support the +20 dBm setting. - This is because of a power class restriction in the controller's QDID. - -See :ref:`ug_radio_fem` for more information about FEM in the |NCS|. - -.. _nrf53_audio_app_building_script: - -Building and programming using script -===================================== - -The suggested method for building the application and programming it to the development kit is running the :file:`buildprog.py` Python script, which is located in the :file:`applications/nrf5340_audio/tools/buildprog` directory. -The script automates the process of selecting :ref:`configuration files ` and building different versions of the application. -This eases the process of building and programming images for multiple development kits. - -Preparing the JSON file ------------------------ - -The script depends on the settings defined in the :file:`nrf5340_audio_dk_devices.json` file. -Before using the script, make sure to update this file with the following information for each development kit you want to use: - -* ``nrf5340_audio_dk_snr`` -- This field lists the SEGGER serial number. - You can check this number on the sticker on the nRF5340 Audio development kit. - Alternatively, connect the development kit to your PC and run ``nrfjprog -i`` in a command window to print the SEGGER serial number of the kit. -* ``nrf5340_audio_dk_dev`` -- This field assigns the specific nRF5340 Audio development kit to be a headset or a gateway. -* ``channel`` -- This field is valid only for headsets operating in the CIS mode. - It sets the channels on which the headset is meant to work. - When no channel is set, the headset is programmed as a left channel one. - -.. _nrf53_audio_app_building_script_running: - -Running the script ------------------- - -After editing the :file:`nrf5340_audio_dk_devices.json` file, run :file:`buildprog.py` to build the firmware for the development kits. -The building command for running the script requires providing the following parameters, in line with :ref:`nrf53_audio_app_configuration_files`: - -* Core type (``-c`` parameter): ``app``, ``net``, or ``both`` -* Application version (``-b`` parameter): either ``release`` or ``debug`` -* Device type (``-d`` parameter): ``headset``, ``gateway``, or ``both`` -* DFU type (``-m`` parameter): ``internal``, ``external`` -* Network core bootloader minimal size (``-M``) - -See the following examples of the parameter usage with the command run from the :file:`buildprog` directory: - -* Example 1: The following command builds the application using the script for the application core with the ``debug`` application version for both the headset and the gateway: - - .. code-block:: console - - python buildprog.py -c app -b debug -d both - -* Example 2: The following command builds the application using the script for both the application and the network core (``both``). - It builds with the ``release`` application version, with the DFU internal flash memory layout enabled, and using the minimal size of the network core bootloader: - - .. code-block:: console - - python buildprog.py -c both -b release -d both -m internal -M - - If you run this command with the ``external`` DFU type parameter instead of ``internal``, the external flash memory layout will be enabled. - -The command can be run from any location, as long as the correct path to :file:`buildprog.py` is given. - -The build files are saved in the :file:`applications/nrf5340_audio/build` directory. -The script creates a directory for each application version and device type combination. -For example, when running the command above, the script creates the :file:`dev_gateway/build_debug` and :file:`dev_headset/build_debug` directories. - -Programming with the script - The development kits are programmed according to the serial numbers set in the JSON file. - Make sure to connect the development kits to your PC using USB and turn them on using the **POWER** switch before you run the command. - - The following parameters are available for programming: - - * Programming (``-p`` parameter) -- If you run the building script with this parameter, you can program one or both of the cores after building the files. - * Sequential programming (``-s`` parameter) -- If you are using Windows Subsystem for Linux (WSL) and encounter problems while programming, include this parameter alongside other parameters to program sequentially. - - The command for programming can look as follows: - - .. code-block:: console - - python buildprog.py -c both -b debug -d both -p - - This command builds the application with the ``debug`` application version for both the headset and the gateway and programs the application core. - Given the ``-c both`` parameter, it also takes the precompiled Bluetooth Low Energy Controller binary from the :file:`nrf/lib/bin/bt_ll_acs_nrf53/bin` directory and programs it to the network core of both the gateway and the headset. - - .. note:: - If the programming command fails because of :ref:`readback_protection_error`, run :file:`buildprog.py` with the ``--recover_on_fail`` or ``-f`` parameter to recover and re-program automatically when programming fails. - For example, using the programming command example above: - - .. code-block:: console - - python buildprog.py -c both -b debug -d both -p --recover_on_fail - - If you want to program firmware that has DFU enabled, you must include the DFU parameters in the command. - The command for programming with DFU enabled can look as follows: - - .. code-block:: console - - python buildprog.py -c both -b release -d both -m internal -M -p - -Getting help - Run ``python buildprog.py -h`` for information about all available script parameters. - -Configuration table overview - When running the script command, a table similar to the following one is displayed to provide an overview of the selected options and parameter values: - - .. code-block:: console - - +------------+----------+---------+--------------+---------------------+---------------------+ - | snr | snr conn | device | only reboot | core app programmed | core net programmed | - +------------+----------+---------+--------------+---------------------+---------------------+ - | 1010101010 | True | headset | Not selected | Selected TBD | Not selected | - | 2020202020 | True | gateway | Not selected | Selected TBD | Not selected | - | 3030303030 | True | headset | Not selected | Selected TBD | Not selected | - +------------+----------+---------+--------------+---------------------+---------------------+ - - See the following table for the meaning of each column and the list of possible values: - - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - | Column | Indication | Possible values | - +=======================+=====================================================================================================+=================================================+ - | ``snr`` | Serial number of the device, as provided in the :file:`nrf5340_audio_dk_devices.json` file. | Serial number. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - | ``snr conn`` | Whether the device with the provided serial number is connected to the PC with a serial connection. | ``True`` - Connected. | - | | +-------------------------------------------------+ - | | | ``False`` - Not connected. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - | ``device`` | Device type, as provided in the :file:`nrf5340_audio_dk_devices.json` file. | ``headset`` - Headset. | - | | +-------------------------------------------------+ - | | | ``gateway`` - Gateway. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - | ``only reboot`` | Whether the device is to be only reset and not programmed. | ``Not selected`` - No reset. | - | | This depends on the ``-r`` parameter in the command, which overrides other parameters. +-------------------------------------------------+ - | | | ``Selected TBD`` - Only reset requested. | - | | +-------------------------------------------------+ - | | | ``Done`` - Reset done. | - | | +-------------------------------------------------+ - | | | ``Failed`` - Reset failed. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - |``core app programmed``| Whether the application core is to be programmed. | ``Not selected`` - Core will not be programmed. | - | | This depends on the value provided to the ``-c`` parameter (see above). +-------------------------------------------------+ - | | | ``Selected TBD`` - Programming requested. | - | | +-------------------------------------------------+ - | | | ``Done`` - Programming done. | - | | +-------------------------------------------------+ - | | | ``Failed`` - Programming failed. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - |``core net programmed``| Whether the network core is to be programmed. | ``Not selected`` - Core will not be programmed. | - | | This depends on the value provided to the ``-c`` parameter (see above). +-------------------------------------------------+ - | | | ``Selected TBD`` - Programming requested. | - | | +-------------------------------------------------+ - | | | ``Done`` - Programming done. | - | | +-------------------------------------------------+ - | | | ``Failed`` - Programming failed. | - +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ - -.. _nrf53_audio_app_building_standard: - -Building and programming using command line -=========================================== - -You can also build the nRF5340 Audio application using the standard |NCS| :ref:`build steps ` for the command line. - -.. note:: - Using this method requires you to build and program each development kit one at a time before moving to the next configuration, which can be time-consuming. - :ref:`nrf53_audio_app_building_script` is recommended. - -Building the application ------------------------- - -Complete the following steps to build the application: - -1. Choose the combination of build flags: - - a. Choose the device type by using one of the following options: - - * For headset device: ``-DCONFIG_AUDIO_DEV=1`` - * For gateway device: ``-DCONFIG_AUDIO_DEV=2`` - - #. Choose the application version by using one of the following options: - - * For the debug version: No build flag needed. - * For the release version: ``-DCONF_FILE=prj_release.conf`` - -#. Build the application using the standard :ref:`build steps ` for the command line. - For example, if you want to build the firmware for the application core as a headset using the ``release`` application version, you can run the following command: - - .. code-block:: console - - west build -b nrf5340_audio_dk_nrf5340_cpuapp --pristine -- -DCONFIG_AUDIO_DEV=1 -DCONF_FILE=prj_release.conf - - Unlike when :ref:`nrf53_audio_app_building_script`, this command creates the build files directly in the :file:`build` directory. - This means that you first need to program the headset development kits before you build and program gateway development kits. - Alternatively, you can add the ``-d`` parameter to the ``west`` command to specify a custom build folder. This lets you build firmware for both - headset and gateway before programming any development kits. - -Programming the application ---------------------------- - -After building the files for the development kit you want to program, complete the following steps to program the application from the command line: - -1. Plug the device into the USB port. - - .. note:: - |usb_known_issues| - -#. Turn on the development kit using the On/Off switch. -#. Open a command prompt. -#. Run the following command to print the SEGGER serial number of your development kit: - - .. code-block:: console - - nrfjprog -i - - .. note:: - Pay attention to which device is to be programmed with the gateway HEX file and which devices are to be programmed with the headset HEX file. - -#. Program the network core on the development kit by running the following command: - - .. code-block:: console - - nrfjprog --program bin/*.hex --chiperase --coprocessor CP_NETWORK -r - - |nrf5340_audio_net_core_hex_note| -#. Program the application core on the development kit with the respective HEX file from the :file:`build` directory by running the following command: - - .. code-block:: console - - nrfjprog --program build/zephyr/zephyr.hex --coprocessor CP_APPLICATION --chiperase -r - - In this command, :file:`build/zephyr/zephyr.hex` is the HEX binary file for the application core. - If a custom build folder is specified, the path to this folder must be used instead of :file:`build/`. -#. If any device is not programmed due to :ref:`readback_protection_error`, complete the following steps: - - a. Run the following commands to recover the device: - - .. code-block:: console - - nrfjprog --recover --coprocessor CP_NETWORK - nrfjprog --recover - - #. Repeat steps 5 and 6 to program both cores again. - -#. When using the default CIS configuration, if you want to use two headset devices, you must also populate the UICR with the desired channel for each headset. - Use the following commands, depending on which headset you want to populate: - - * Left headset: - - .. code-block:: console - - nrfjprog --memwr 0x00FF80F4 --val 0 - - * Right headset: - - .. code-block:: console - - nrfjprog --memwr 0x00FF80F4 --val 1 - - Select the correct board when prompted with the popup or add the ``--snr`` parameter followed by the SEGGER serial number of the correct board at the end of the ``nrfjprog`` command. - - -.. _nrf53_audio_app_testing: - -Testing -======= - -After building and programming the application, you can test it for both the CIS and the BIS modes. -The following testing scenarios assume you are using USB as the audio source on the gateway. -This is the default setting. - -.. _nrf53_audio_app_testing_steps_cis: - -Testing the default CIS mode ----------------------------- - -Complete the following steps to test the unidirectional CIS mode for one gateway and two headset devices: - -1. Make sure that the development kits are still plugged into the USB ports and are turned on. - - .. note:: - |usb_known_issues| - - After programming, **RGB2** starts blinking green on every device to indicate the ongoing CPU activity on the network core. - **LED3** starts blinking green on every device to indicate the ongoing CPU activity on the application core. -#. Wait for the **LED1** on the gateway to start blinking blue. - This happens shortly after programming the development kit and indicates that the gateway device is connected to at least one headset and ready to send data. -#. Search the list of audio devices listed in the sound settings of your operating system for *nRF5340 USB Audio* (gateway) and select it as the output device. -#. Connect headphones to the **HEADPHONE** audio jack on both headset devices. -#. Start audio playback on your PC from any source. -#. Wait for **LED1** to blink blue on both headsets. - When they do, the audio stream has started on both headsets. - - .. note:: - The audio outputs only to the left channel of the audio jack, even if the given headset is configured as the right headset. - This is because of the mono hardware codec chip used on the development kits. - If you want to play stereo sound using one development kit, you must connect an external hardware codec chip that supports stereo. - -#. Wait for **LED2** to light up solid green on the headsets to indicate that the audio synchronization is achieved. -#. Press the **VOL+** button on one of the headsets. - The playback volume increases for both headsets. -#. Press the **VOL-** button on the gateway. - The playback volume decreases for both headsets. -#. Press the **PLAY/PAUSE** button on any one of the devices. - The playback stops for both headsets and the streaming state for all devices is set to paused. -#. Press the **RESET** button on the gateway. - The gateway resets and the playback on the unpaused headset stops. - After some time, the gateway establishes the connection with both headsets and resumes the playback on the unpaused headset. -#. Press the **PLAY/PAUSE** button on any one of the devices. - The playback resumes in both headsets. -#. Press the **BTN 4** button on the gateway multiple times. - For each button press, the audio stream playback is stopped and the gateway sends a test tone to both headsets. - These tones can be used as audio cues to check the synchronization of the headsets. -#. Hold down the **VOL+** button and press the **RESET** button on the left headset. - After startup, this headset will be configured as the right channel headset. -#. Hold down the **VOL-** button and press the **RESET** button on the left headset. - After startup, this headset will go back to be configured as the left channel headset. - You can also just press the **RESET** button to restore the original programmed settings. - -After the kits have paired for the first time, they are now bonded. -This means the Long-Term Key (LTK) is stored on each side, and that the kits will only connect to each other unless the bonding information is cleared. -To clear the bonding information, press and hold **BTN 5** during boot. - -When you finish testing, power off the nRF5340 Audio development kits by switching the power switch from On to Off. - -.. _nrf53_audio_app_testing_steps_bis: - -Testing the BIS mode --------------------- - -Testing the BIS mode is identical to `Testing the default CIS mode`_, except for the following differences: - -* You must :ref:`select the BIS mode manually ` before building the application. -* You can play the audio stream with different audio settings on the receivers. - For example, you can decrease or increase the volume separately for each receiver during playback. -* When pressing the **PLAY/PAUSE** button on a headset, the streaming state only changes for that given headset. -* Pressing the **PLAY/PAUSE** button on the gateway will respectively start or stop the stream for all headsets listening in. -* Pressing the **BTN 4** button on a headset will change the active audio stream. - The default configuration of the BIS mode supports two audio streams (left and right). -* Pressing the **BTN 5** button on a headset will change the gateway source for the audio stream (after `Enabling the BIS mode with two gateways`_). - If a second gateway is not present, the headset will not play audio. - -.. _nrf53_audio_app_testing_steps_cis_walkie_talkie: - -Testing the walkie-talkie demo ------------------------------- - -Testing the walkie-talkie demo is identical to `Testing the default CIS mode`_, except for the following differences: - -* You must enable the Kconfig option mentioned in `Enabling the walkie-talkie demo`_ before building the application. -* Instead of controlling the playback, you can speak through the PDM microphones. - The line is open all the time, no need to press any buttons to talk, but the volume control works as in `Testing the default CIS mode`_. - -.. _nrf53_audio_app_porting_guide: - -Testing FOTA upgrades ---------------------- - -`nRF Connect Device Manager`_ can be used for testing FOTA upgrades. -The procedure for upgrading the firmware is identical for both headset and gateway firmware. -You can test upgrading the firmware on both cores at the same time on a headset device by completing the following steps: - -1. Make sure you have :ref:`configured the application for FOTA `. -#. Install `nRF Connect Device Manager`_ on your Android or iOS device. -#. Connect an external flash shield to the headset. -#. Make sure the headset runs a firmware that supports DFU using external flash memory. - One way of doing this is to connect the headset to the USB port, turn it on, and then run this command: - - .. code-block:: console - - python buildprog.py -c both -b debug -d headset --pristine -m external -p - - .. note:: - When using the FOTA related functionality in the :file:`buildprog.py` script on Linux, the ``python`` command must execute Python 3. - -#. Use the :file:`buildprog.py` script to create a zip file that contains new firmware for both cores: - - .. code-block:: console - - python buildprog.py -c both -b debug -d headset --pristine -m external - -#. Transfer the generated file to your Android or iOS device, depending on the DFU scenario. - See the `FOTA build files`_ section for information about FOTA file name patterns. - For transfer, you can use cloud services like Google Drive for Android or iCloud for iOS. -#. Enter the DFU mode by pressing and holding down **RESET** and **BTN 4** at the same time, and then releasing **RESET** while continuing to hold down **BTN 4** for a couple more seconds. -#. Open `nRF Connect Device Manager`_ and look for ``NRF5340_AUDIO_HL_DFU`` in the scanned devices window. - The headset is left by default. -#. Tap on :guilabel:`NRF5340_AUDIO_HL_DFU` and then on the downward arrow icon at the bottom of the screen. -#. In the :guilabel:`Firmware Upgrade` section, tap :guilabel:`SELECT FILE`. -#. Select the file you transferred to the device. -#. Tap :guilabel:`START` and check :guilabel:`Confirm only` in the notification. -#. Tap :guilabel:`START` again to start the DFU process. -#. When the DFU has finished, verify that the new application core and network core firmware works properly. - -Dependencies -************ - -.. note:: - The following lists mention the most important dependencies. - For the full list, check the application's Kconfig options. - All dependencies are automatically included. - -The application uses the following |NCS| components: - -* :ref:`lib_bt_ll_acs_nrf53_readme` -* :ref:`lib_contin_array` -* :ref:`lib_pcm_mix` -* :ref:`lib_tone` - -This application uses the following `nrfx`_ libraries: - -* :file:`nrfx_clock.h` -* :file:`nrfx_gpiote.h` -* :file:`nrfx_timer.h` -* :file:`nrfx_dppi.h` -* :file:`nrfx_i2s.h` -* :file:`nrfx_ipc.h` -* :file:`nrfx_nvmc.h` - -The application also depends on the following Zephyr libraries: - -* :ref:`zephyr:logging_api` -* :ref:`zephyr:kernel_api` -* :ref:`zephyr:zbus` -* :ref:`zephyr:api_peripherals`: - - * :ref:`zephyr:usb_api` - -* :ref:`zephyr:bluetooth_api`: - - * :file:`include/bluetooth/bluetooth.h` - * :file:`include/bluetooth/gatt.h` - * :file:`include/bluetooth/hci.h` - * :file:`include/bluetooth/uuid.h` - -.. _nrf53_audio_app_options: -.. _config_nrf53_audio_app_options: - -Application configuration options -********************************* - -.. options-from-kconfig:: - :show-type: - -.. |usb_known_issues| replace:: Make sure to check the :ref:`nRF5340 Audio application known issues ` related to serial connection with the USB. diff --git a/applications/nrf5340_audio/broadcast_sink/CMakeLists.txt b/applications/nrf5340_audio/broadcast_sink/CMakeLists.txt new file mode 100644 index 00000000000..5c48ca62e4c --- /dev/null +++ b/applications/nrf5340_audio/broadcast_sink/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) diff --git a/applications/nrf5340_audio/broadcast_sink/Kconfig.defaults b/applications/nrf5340_audio/broadcast_sink/Kconfig.defaults new file mode 100644 index 00000000000..107e5b2ad06 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_sink/Kconfig.defaults @@ -0,0 +1,64 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +## ACL related configs ## +config BT_OBSERVER + default y + +config BT_PERIPHERAL + default y + +# Generic Audio Sink - 0x0840 +config BT_DEVICE_APPEARANCE + default 2112 + +config BT_PER_ADV_SYNC_MAX + default 2 + +config BT_SMP + default y + + +## ISO related configs ## +config BT_ISO_SYNC_RECEIVER + default y + +config BT_BAP_BROADCAST_SINK + default y + +config BT_BAP_SCAN_DELEGATOR + default y + +config BT_BAP_BROADCAST_SNK_STREAM_COUNT + default 2 + +config BT_BAP_BROADCAST_SNK_COUNT + default 2 + +config BT_ISO_MAX_CHAN + default 2 + +config BT_ISO_MAX_BIG + default 2 + +config BT_PAC_SNK + default y + +config BT_AUDIO_RX + default y + + +## Audio related configs ## +config AUDIO_MUTE + default n + +config AUDIO_TEST_TONE + default n + + +## LC3 related configs ## +config LC3_DEC_CHAN_MAX + default 1 diff --git a/applications/nrf5340_audio/broadcast_sink/README.rst b/applications/nrf5340_audio/broadcast_sink/README.rst new file mode 100644 index 00000000000..46dbce53847 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_sink/README.rst @@ -0,0 +1,107 @@ +.. _nrf53_audio_broadcast_sink_app: + +nRF5340 Audio: Broadcast sink +############################# + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio broadcast sink application implements the :ref:`BIS headset mode `. +In this mode, receiving broadcast audio happens using Broadcast Isochronous Stream (BIS) and Broadcast Isochronous Group (BIG). + +The following limitations apply to this application: + +* One BIG, one of the two BIS streams (selectable). +* Audio output: I2S/Analog headset output. +* Configuration: 16 bit, several bit rates ranging from 32 kbps to 124 kbps. + +.. _nrf53_audio_broadcast_sink_app_requirements: + +Requirements +************ + +The application shares the :ref:`requirements common to all nRF5340 Audio application `. + +.. _nrf53_audio_broadcast_sink_app_ui: + +User interface +************** + +Most of the user interface mappings are common across all nRF5340 Audio applications. +See the :ref:`nrf53_audio_app_ui` page for detailed overview. + +This application uses specific mapping for the following user interface elements: + +* Long-pressed on the broadcast sink device during startup: + + * **VOL-** - Changes the headset to the left channel one. + * **VOL+** - Changes the headset to the right channel one. + +* Pressed on the broadcast sink device during playback: + + * **PLAY/PAUSE** - Starts or pauses listening to the stream. + * **VOL-** - Turns the playback volume down. + * **VOL+** - Turns the playback volume up. + * **BTN 4** - Changes audio stream (different BIS), if more than one is available. + * **BTN 5** - Changes the gateway, if more than one is available. + +* **LED1**: + + * Solid blue - Devices have synchronized with a broadcasted stream. + * Blinking blue - Devices have started streaming audio (BIS mode). + +* **LED2** - Solid green - Sync achieved (both drift and presentation compensation are in the ``LOCKED`` state). +* **RGB**: + + * Solid blue - The device is programmed as the left headset. + * Solid magenta - The device is programmed as the right headset. + +.. _nrf53_audio_broadcast_sink_app_configuration: + +Configuration +************* + +The application requires the ``CONFIG_TRANSPORT_BIS`` Kconfig option to be set to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file for `Building and running`_ to succeed. + +For other configuration options, see :ref:`nrf53_audio_app_configuration` and :ref:`nrf53_audio_app_fota`. + +For information about how to configure applications in the |NCS|, see :ref:`configure_application`. + +.. _nrf53_audio_broadcast_sink_app_building: + +Building and running +******************** + +This application can be found under :file:`applications/nrf5340_audio/broadcast_sink` in the nRF Connect SDK folder structure, but it uses :file:`.conf` files at :file:`applications/nrf5340_audio/`. + +The nRF5340 Audio DK comes preprogrammed with basic firmware that indicates if the kit is functional. +See :ref:`nrf53_audio_app_dk_testing_out_of_the_box` for more information. + +To build the application, complete the following steps: + +1. Select the BIS mode by setting the ``CONFIG_TRANSPORT_BIS`` Kconfig option to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file for the debug version and in the :file:`applications/nrf5340_audio/prj_release.conf` file for the release version. +#. Complete the steps for building and programming common to all audio applications using one of the following methods: + + * :ref:`nrf53_audio_app_building_script` + * :ref:`nrf53_audio_app_building_standard` + +.. _nrf53_audio_broadcast_sink_app_testing: + +Testing +******* + +.. note:: + |nrf5340_audio_external_devices_note| + +To test the broadcast sink application, complete the following steps: + +1. Make sure you have another nRF5340 Audio DK for testing purposes. +#. Program the other DK with the :ref:`broadcast source ` application. + The broadcast sink device automatically synchronizes with the broadcast source after programming. +#. Proceed to testing the devices using the :ref:`nrf53_audio_broadcast_sink_app_ui` buttons and LEDs. + +Dependencies +************ + +For the list of dependencies, check the application's source files under :file:`applications/nrf5340_audio/broadcast_sink`. diff --git a/applications/nrf5340_audio/broadcast_sink/main.c b/applications/nrf5340_audio/broadcast_sink/main.c new file mode 100644 index 00000000000..d757295dd58 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_sink/main.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "streamctrl.h" + +#include +#include + +#include "nrf5340_audio_common.h" +#include "nrf5340_audio_dk.h" +#include "broadcast_sink.h" +#include "led.h" +#include "button_assignments.h" +#include "macros_common.h" +#include "audio_system.h" +#include "bt_mgmt.h" +#include "bt_rendering_and_capture.h" +#include "audio_datapath.h" +#include "le_audio_rx.h" + +#include +LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL); + +struct ble_iso_data { + uint8_t data[CONFIG_BT_ISO_RX_MTU]; + size_t data_size; + bool bad_frame; + uint32_t sdu_ref; + uint32_t recv_frame_ts; +} __packed; + +ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); + +ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); + +ZBUS_CHAN_DECLARE(button_chan); +ZBUS_CHAN_DECLARE(le_audio_chan); +ZBUS_CHAN_DECLARE(bt_mgmt_chan); +ZBUS_CHAN_DECLARE(volume_chan); + +ZBUS_OBS_DECLARE(volume_evt_sub); + +static struct k_thread button_msg_sub_thread_data; +static struct k_thread le_audio_msg_sub_thread_data; + +static k_tid_t button_msg_sub_thread_id; +static k_tid_t le_audio_msg_sub_thread_id; + +K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); +K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); + +static enum stream_state strm_state = STATE_PAUSED; + +/* Function for handling all stream state changes */ +static void stream_state_set(enum stream_state stream_state_new) +{ + strm_state = stream_state_new; +} + +/** + * @brief Handle button activity. + */ +static void button_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + bool broadcast_alt = true; + + while (1) { + ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); + ERR_CHK(ret); + + struct button_msg msg; + + ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); + ERR_CHK(ret); + + LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, + msg.button_action); + + if (msg.button_action != BUTTON_PRESS) { + LOG_WRN("Unhandled button action"); + continue; + } + + switch (msg.button_pin) { + case BUTTON_PLAY_PAUSE: + if (strm_state == STATE_STREAMING) { + ret = broadcast_sink_stop(); + if (ret) { + LOG_WRN("Failed to stop broadcast sink: %d", ret); + } + } else if (strm_state == STATE_PAUSED) { + ret = broadcast_sink_start(); + if (ret) { + LOG_WRN("Failed to start broadcast sink: %d", ret); + } + } else { + LOG_WRN("In invalid state: %d", strm_state); + } + + break; + + case BUTTON_VOLUME_UP: + ret = bt_r_and_c_volume_up(); + if (ret) { + LOG_WRN("Failed to increase volume: %d", ret); + } + + break; + + case BUTTON_VOLUME_DOWN: + ret = bt_r_and_c_volume_down(); + if (ret) { + LOG_WRN("Failed to decrease volume: %d", ret); + } + + break; + + case BUTTON_4: + ret = broadcast_sink_change_active_audio_stream(); + if (ret) { + LOG_WRN("Failed to change active audio stream: %d", ret); + } + + break; + + case BUTTON_5: + if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { + ret = bt_r_and_c_volume_mute(false); + if (ret) { + LOG_WRN("Failed to mute, ret: %d", ret); + } + + break; + } + + ret = broadcast_sink_disable(); + if (ret) { + LOG_ERR("Failed to disable the broadcast sink: %d", ret); + break; + } + + if (broadcast_alt) { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, + CONFIG_BT_AUDIO_BROADCAST_NAME_ALT, + BRDCAST_ID_NOT_USED); + broadcast_alt = false; + } else { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, + CONFIG_BT_AUDIO_BROADCAST_NAME, + BRDCAST_ID_NOT_USED); + broadcast_alt = true; + } + + if (ret) { + LOG_WRN("Failed to start scanning for broadcaster: %d", ret); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); + } + + STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); + } +} + +/** + * @brief Handle Bluetooth LE audio events. + */ +static void le_audio_msg_sub_thread(void) +{ + int ret; + uint32_t pres_delay_us; + uint32_t bitrate_bps; + uint32_t sampling_rate_hz; + + const struct zbus_channel *chan; + + while (1) { + struct le_audio_msg msg; + + ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); + ERR_CHK(ret); + + LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); + + switch (msg.event) { + case LE_AUDIO_EVT_STREAMING: + LOG_DBG("LE audio evt streaming"); + + if (strm_state == STATE_STREAMING) { + LOG_DBG("Got streaming event in streaming state"); + break; + } + + audio_system_start(); + stream_state_set(STATE_STREAMING); + ret = led_blink(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + case LE_AUDIO_EVT_NOT_STREAMING: + LOG_DBG("LE audio evt not_streaming"); + + if (strm_state == STATE_PAUSED) { + LOG_DBG("Got not_streaming event in paused state"); + break; + } + + stream_state_set(STATE_PAUSED); + audio_system_stop(); + ret = led_on(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + case LE_AUDIO_EVT_CONFIG_RECEIVED: + LOG_DBG("LE audio config received"); + + ret = broadcast_sink_config_get(&bitrate_bps, &sampling_rate_hz, + &pres_delay_us); + if (ret) { + LOG_WRN("Failed to get config: %d", ret); + break; + } + + LOG_DBG("\tSampling rate: %d Hz", sampling_rate_hz); + LOG_DBG("\tBitrate (compressed): %d bps", bitrate_bps); + + ret = audio_system_config_set(VALUE_NOT_SET, VALUE_NOT_SET, + sampling_rate_hz); + ERR_CHK(ret); + + ret = audio_datapath_pres_delay_us_set(pres_delay_us); + if (ret) { + LOG_ERR("Failed to set presentation delay to %d", pres_delay_us); + break; + } + + LOG_INF("Presentation delay %d us is set", pres_delay_us); + + break; + + case LE_AUDIO_EVT_SYNC_LOST: + LOG_INF("Sync lost"); + + ret = bt_mgmt_pa_sync_delete(msg.pa_sync); + if (ret) { + LOG_WRN("Failed to delete PA sync"); + } + + if (strm_state == STATE_STREAMING) { + stream_state_set(STATE_PAUSED); + audio_system_stop(); + ret = led_on(LED_APP_1_BLUE); + ERR_CHK(ret); + } + + if (IS_ENABLED(CONFIG_BT_OBSERVER)) { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL, + BRDCAST_ID_NOT_USED); + if (ret) { + if (ret == -EALREADY) { + break; + } + + LOG_ERR("Failed to restart scanning: %d", ret); + break; + } + + /* NOTE: The string below is used by the Nordic CI system */ + LOG_INF("Restarted scanning for broadcaster"); + } + + break; + + case LE_AUDIO_EVT_NO_VALID_CFG: + LOG_WRN("No valid configurations found, disabling the broadcast sink"); + + ret = broadcast_sink_disable(); + if (ret) { + LOG_ERR("Failed to disable the broadcast sink: %d", ret); + break; + } + + break; + + default: + LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); + + break; + } + + STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); + } +} + +/** + * @brief Create zbus subscriber threads. + * + * @return 0 for success, error otherwise. + */ +static int zbus_subscribers_create(void) +{ + int ret; + + button_msg_sub_thread_id = k_thread_create( + &button_msg_sub_thread_data, button_msg_sub_thread_stack, + CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create button_msg thread"); + return ret; + } + + le_audio_msg_sub_thread_id = k_thread_create( + &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, + CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create le_audio_msg thread"); + return ret; + } + + return 0; +} + +/** + * @brief Zbus listener to receive events from bt_mgmt. + * + * @param[in] chan Zbus channel. + * + * @note Will in most cases be called from BT_RX context, + * so there should not be too much processing done here. + */ +static void bt_mgmt_evt_handler(const struct zbus_channel *chan) +{ + int ret; + const struct bt_mgmt_msg *msg; + + msg = zbus_chan_const_msg(chan); + + switch (msg->event) { + case BT_MGMT_PA_SYNCED: + LOG_DBG("PA synced"); + + ret = broadcast_sink_pa_sync_set(msg->pa_sync, msg->broadcast_id); + if (ret) { + LOG_WRN("Failed to set PA sync"); + } + + break; + + case BT_MGMT_PA_SYNC_LOST: + LOG_INF("PA sync lost, reason: %d", msg->pa_sync_term_reason); + + if (IS_ENABLED(CONFIG_BT_OBSERVER) && + msg->pa_sync_term_reason != BT_HCI_ERR_LOCALHOST_TERM_CONN) { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL, + BRDCAST_ID_NOT_USED); + if (ret) { + if (ret == -EALREADY) { + return; + } + + LOG_ERR("Failed to restart scanning: %d", ret); + break; + } + + /* NOTE: The string below is used by the Nordic CI system */ + LOG_INF("Restarted scanning for broadcaster"); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); + + break; + } +} + +ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); + +/** + * @brief Link zbus producers and observers. + * + * @return 0 for success, error otherwise. + */ +static int zbus_link_producers_observers(void) +{ + int ret; + + if (!IS_ENABLED(CONFIG_ZBUS)) { + return -ENOTSUP; + } + + ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add button sub"); + return ret; + } + + ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add le_audio sub"); + return ret; + } + + ret = zbus_chan_add_obs(&volume_chan, &volume_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add add volume sub"); + return ret; + } + + ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add bt_mgmt listener"); + return ret; + } + + return 0; +} + +uint8_t stream_state_get(void) +{ + return strm_state; +} + +void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) +{ + ARG_UNUSED(data); + ARG_UNUSED(size); + ARG_UNUSED(num_ch); + + LOG_WRN("Sending is not possible for broadcast sink"); +} + +int main(void) +{ + int ret; + + LOG_DBG("nRF5340 APP core started"); + + ret = nrf5340_audio_dk_init(); + ERR_CHK(ret); + + ret = nrf5340_audio_common_init(); + ERR_CHK(ret); + + ret = zbus_subscribers_create(); + ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); + + ret = zbus_link_producers_observers(); + ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); + + ret = le_audio_rx_init(); + ERR_CHK_MSG(ret, "Failed to initialize rx path"); + + ret = broadcast_sink_enable(le_audio_rx_data_handler); + ERR_CHK_MSG(ret, "Failed to enable broadcast sink"); + + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, CONFIG_BT_AUDIO_BROADCAST_NAME, + BRDCAST_ID_NOT_USED); + ERR_CHK_MSG(ret, "Failed to start scanning"); + + return 0; +} diff --git a/applications/nrf5340_audio/broadcast_source/CMakeLists.txt b/applications/nrf5340_audio/broadcast_source/CMakeLists.txt new file mode 100644 index 00000000000..5c48ca62e4c --- /dev/null +++ b/applications/nrf5340_audio/broadcast_source/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) diff --git a/applications/nrf5340_audio/broadcast_source/Kconfig.defaults b/applications/nrf5340_audio/broadcast_source/Kconfig.defaults new file mode 100644 index 00000000000..0861c049295 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_source/Kconfig.defaults @@ -0,0 +1,42 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +## ISO related configs ## +config BT_CAP_INITIATOR + default y + +config BT_MAX_CONN + default 1 + +# Broadcasting Device - 0x0885 +config BT_DEVICE_APPEARANCE + default 2181 + +config BT_ISO_BROADCASTER + default y + +config BT_BAP_BROADCAST_SOURCE + default y + +config BT_ISO_TX_BUF_COUNT + default 2 + +config BT_BAP_BROADCAST_SRC_STREAM_COUNT + default 2 + +config BT_ISO_MAX_CHAN + default 2 + +config BT_AUDIO_TX + default y + + +## LC3 related configs ## +config LC3_BITRATE + default BT_AUDIO_BITRATE_BROADCAST_SRC + +config LC3_ENC_CHAN_MAX + default 2 diff --git a/applications/nrf5340_audio/broadcast_source/README.rst b/applications/nrf5340_audio/broadcast_source/README.rst new file mode 100644 index 00000000000..0772de343a4 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_source/README.rst @@ -0,0 +1,96 @@ +.. _nrf53_audio_broadcast_source_app: + +nRF5340 Audio: Broadcast source +############################### + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio broadcast source application implements the :ref:`BIS gateway mode `. + +In this mode, transmitting broadcast audio happens using Broadcast Isochronous Stream (BIS) and Broadcast Isochronous Group (BIG). +Play and pause are emulated by enabling and disabling stream, respectively. + +The following limitations apply to this application: + +* One BIG with two BIS streams. +* Audio input: USB or I2S (Line in or using Pulse Density Modulation). +* Configuration: 16 bit, several bit rates ranging from 32 kbps to 124 kbps. + +.. _nrf53_audio_broadcast_source_app_requirements: + +Requirements +************ + +The application shares the :ref:`requirements common to all nRF5340 Audio application `. + +.. _nrf53_audio_broadcast_source_app_ui: + +User interface +************** + +Most of the user interface mappings are common across all nRF5340 Audio applications. +See the :ref:`nrf53_audio_app_ui` page for detailed overview. + +This application uses specific mapping for the following user interface elements: + +* Pressed on the broadcast source device during playback: + + * **PLAY/PAUSE** - Starts or pauses the playback of the stream. + * **BTN 4** - Toggles between the normal audio stream and different test tones generated on the device. + Use this tone to check the synchronization of headsets. + +* **LED1** - Blinking blue - Device has started broadcasting audio. +* **RGB** - Solid green - The device is programmed as the gateway. + +.. _nrf53_audio_broadcast_source_app_configuration: + +Configuration +************* + +The application requires the ``CONFIG_TRANSPORT_BIS`` Kconfig option to be set to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file for `Building and running`_ to succeed. + +For other configuration options, see :ref:`nrf53_audio_app_configuration` and :ref:`nrf53_audio_app_fota`. + +For information about how to configure applications in the |NCS|, see :ref:`configure_application`. + +.. _nrf53_audio_broadcast_source_app_building: + +Building and running +******************** + +This application can be found under :file:`applications/nrf5340_audio/broadcast_source` in the nRF Connect SDK folder structure, but it uses :file:`.conf` files at :file:`applications/nrf5340_audio/`. + +The nRF5340 Audio DK comes preprogrammed with basic firmware that indicates if the kit is functional. +See :ref:`nrf53_audio_app_dk_testing_out_of_the_box` for more information. + +To build the application, complete the following steps: + +1. Select the BIS mode by setting the ``CONFIG_TRANSPORT_BIS`` Kconfig option to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file for the debug version and in the :file:`applications/nrf5340_audio/prj_release.conf` file for the release version. +#. Complete the steps for building and programming common to all audio applications using one of the following methods: + + * :ref:`nrf53_audio_app_building_script` + * :ref:`nrf53_audio_app_building_standard` + +After programming, the broadcast source automatically starts broadcasting the default 48-kHz audio stream. + +.. _nrf53_audio_broadcast_source_app_testing: + +Testing +******* + +.. note:: + |nrf5340_audio_external_devices_note| + +To test the broadcast source application, complete the following steps: + +1. Make sure you have another nRF5340 Audio DK for testing purposes. +#. Program the other DK with the :ref:`broadcast sink ` application. + The broadcast sink device automatically synchronizes with the broadcast source after programming. +#. Proceed to testing the broadcast source using the :ref:`nrf53_audio_broadcast_source_app_ui` buttons and LEDs. + +Dependencies +************ + +For the list of dependencies, check the application's source files. diff --git a/applications/nrf5340_audio/broadcast_source/main.c b/applications/nrf5340_audio/broadcast_source/main.c new file mode 100644 index 00000000000..2ab7767d220 --- /dev/null +++ b/applications/nrf5340_audio/broadcast_source/main.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "streamctrl.h" + +#include +#include +#include + +#include "nrf5340_audio_common.h" +#include "nrf5340_audio_dk.h" +#include "broadcast_source.h" +#include "led.h" +#include "button_assignments.h" +#include "macros_common.h" +#include "audio_system.h" +#include "bt_mgmt.h" + +#include +LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL); + +ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); + +ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); + +ZBUS_CHAN_DECLARE(button_chan); +ZBUS_CHAN_DECLARE(le_audio_chan); +ZBUS_CHAN_DECLARE(bt_mgmt_chan); +ZBUS_CHAN_DECLARE(sdu_ref_chan); + +ZBUS_OBS_DECLARE(sdu_ref_msg_listen); + +static struct k_thread button_msg_sub_thread_data; +static struct k_thread le_audio_msg_sub_thread_data; + +static k_tid_t button_msg_sub_thread_id; +static k_tid_t le_audio_msg_sub_thread_id; + +K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); +K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); + +static enum stream_state strm_state = STATE_PAUSED; + +/* Function for handling all stream state changes */ +static void stream_state_set(enum stream_state stream_state_new) +{ + strm_state = stream_state_new; +} + +/** + * @brief Handle button activity. + */ +static void button_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + + while (1) { + ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); + ERR_CHK(ret); + + struct button_msg msg; + + ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); + ERR_CHK(ret); + + LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, + msg.button_action); + + if (msg.button_action != BUTTON_PRESS) { + LOG_WRN("Unhandled button action"); + return; + } + + switch (msg.button_pin) { + case BUTTON_PLAY_PAUSE: + if (strm_state == STATE_STREAMING) { + ret = broadcast_source_stop(); + if (ret) { + LOG_WRN("Failed to stop broadcaster: %d", ret); + } + } else if (strm_state == STATE_PAUSED) { + ret = broadcast_source_start(NULL); + if (ret) { + LOG_WRN("Failed to start broadcaster: %d", ret); + } + } else { + LOG_WRN("In invalid state: %d", strm_state); + } + + break; + + case BUTTON_4: + if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { + if (strm_state != STATE_STREAMING) { + LOG_WRN("Not in streaming state"); + break; + } + + ret = audio_system_encode_test_tone_step(); + if (ret) { + LOG_WRN("Failed to play test tone, ret: %d", ret); + } + + break; + } + + break; + + default: + LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); + } + + STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); + } +} + +/** + * @brief Handle Bluetooth LE audio events. + */ +static void le_audio_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + + while (1) { + struct le_audio_msg msg; + + ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); + ERR_CHK(ret); + + LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); + + switch (msg.event) { + case LE_AUDIO_EVT_STREAMING: + LOG_DBG("LE audio evt streaming"); + + audio_system_encoder_start(); + + if (strm_state == STATE_STREAMING) { + LOG_DBG("Got streaming event in streaming state"); + break; + } + + audio_system_start(); + stream_state_set(STATE_STREAMING); + ret = led_blink(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + case LE_AUDIO_EVT_NOT_STREAMING: + LOG_DBG("LE audio evt not_streaming"); + + audio_system_encoder_stop(); + + if (strm_state == STATE_PAUSED) { + LOG_DBG("Got not_streaming event in paused state"); + break; + } + + stream_state_set(STATE_PAUSED); + audio_system_stop(); + ret = led_on(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + default: + LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); + + break; + } + + STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); + } +} + +/** + * @brief Create zbus subscriber threads. + * + * @return 0 for success, error otherwise. + */ +static int zbus_subscribers_create(void) +{ + int ret; + + button_msg_sub_thread_id = k_thread_create( + &button_msg_sub_thread_data, button_msg_sub_thread_stack, + CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create button_msg thread"); + return ret; + } + + le_audio_msg_sub_thread_id = k_thread_create( + &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, + CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create le_audio_msg thread"); + return ret; + } + + ret = zbus_chan_add_obs(&sdu_ref_chan, &sdu_ref_msg_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add timestamp listener"); + return ret; + } + + return 0; +} + +/** + * @brief Zbus listener to receive events from bt_mgmt. + * + * @param[in] chan Zbus channel. + * + * @note Will in most cases be called from BT_RX context, + * so there should not be too much processing done here. + */ +static void bt_mgmt_evt_handler(const struct zbus_channel *chan) +{ + int ret; + const struct bt_mgmt_msg *msg; + + msg = zbus_chan_const_msg(chan); + + switch (msg->event) { + case BT_MGMT_EXT_ADV_WITH_PA_READY: + LOG_INF("Ext adv ready"); + + ret = broadcast_source_start(msg->ext_adv); + if (ret) { + LOG_ERR("Failed to start broadcaster: %d", ret); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); + break; + } +} + +ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); + +/** + * @brief Link zbus producers and observers. + * + * @return 0 for success, error otherwise. + */ +static int zbus_link_producers_observers(void) +{ + int ret; + + if (!IS_ENABLED(CONFIG_ZBUS)) { + return -ENOTSUP; + } + + ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add button sub"); + return ret; + } + + ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add le_audio sub"); + return ret; + } + + ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add bt_mgmt listener"); + return ret; + } + + return 0; +} + +uint8_t stream_state_get(void) +{ + return strm_state; +} + +void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) +{ + int ret; + static int prev_ret; + + struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; + + if (strm_state == STATE_STREAMING) { + ret = broadcast_source_send(enc_audio); + + if (ret != 0 && ret != prev_ret) { + if (ret == -ECANCELED) { + LOG_WRN("Sending operation cancelled"); + } else { + LOG_WRN("Problem with sending LE audio data, ret: %d", ret); + } + } + + prev_ret = ret; + } +} + +int main(void) +{ + int ret; + static const struct bt_data *ext_adv; + static const struct bt_data *per_adv; + + LOG_DBG("nRF5340 APP core started"); + + ret = nrf5340_audio_dk_init(); + ERR_CHK(ret); + + ret = nrf5340_audio_common_init(); + ERR_CHK(ret); + + size_t ext_adv_size = 0; + size_t per_adv_size = 0; + + ret = zbus_subscribers_create(); + ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); + + ret = zbus_link_producers_observers(); + ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); + + ret = broadcast_source_enable(); + ERR_CHK_MSG(ret, "Failed to enable broadcaster"); + + ret = audio_system_config_set( + bt_audio_codec_cfg_freq_to_freq_hz(CONFIG_BT_AUDIO_PREF_SAMPLE_RATE_VALUE), + CONFIG_BT_AUDIO_BITRATE_BROADCAST_SRC, VALUE_NOT_SET); + ERR_CHK_MSG(ret, "Failed to set sample- and bitrate"); + + broadcast_source_adv_get(&ext_adv, &ext_adv_size, &per_adv, &per_adv_size); + + ret = bt_mgmt_adv_start(ext_adv, ext_adv_size, per_adv, per_adv_size, false); + ERR_CHK_MSG(ret, "Failed to start advertiser"); + + return 0; +} diff --git a/applications/nrf5340_audio/child_image/hci_ipc.conf b/applications/nrf5340_audio/child_image/hci_ipc.conf index 2a7e8c2ad0f..ff93820e55a 100644 --- a/applications/nrf5340_audio/child_image/hci_ipc.conf +++ b/applications/nrf5340_audio/child_image/hci_ipc.conf @@ -29,3 +29,8 @@ CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=251 # audio clock to be synchronized CONFIG_MPSL_TRIGGER_IPC_TASK_ON_RTC_START=y CONFIG_MPSL_TRIGGER_IPC_TASK_ON_RTC_START_CHANNEL=4 + +# Needed for builds with nrf21540 +# Can also be set to 20, but check local restrictions first +#CONFIG_BT_CTLR_TX_PWR_ANTENNA=10 +#CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=10 diff --git a/applications/nrf5340_audio/child_image/hci_ipc_release.conf b/applications/nrf5340_audio/child_image/hci_ipc_release.conf new file mode 100644 index 00000000000..79c67d8d3bb --- /dev/null +++ b/applications/nrf5340_audio/child_image/hci_ipc_release.conf @@ -0,0 +1,42 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_BT_ISO_PERIPHERAL=y +CONFIG_BT_ISO_CENTRAL=y +CONFIG_BT_ISO_BROADCASTER=y +CONFIG_BT_ISO_SYNC_RECEIVER=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER=y +CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y + +CONFIG_BT_CTLR_CONN_ISO_GROUPS=1 +CONFIG_BT_CTLR_CONN_ISO_STREAMS=2 +CONFIG_BT_CTLR_SYNC_ISO_STREAM_COUNT=2 +CONFIG_BT_CTLR_ADV_ISO_SET=1 +CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT=2 + +# Support two links as a central, or one link as a peripheral +CONFIG_BT_MAX_CONN=3 +CONFIG_BT_CTLR_SDC_PERIPHERAL_COUNT=1 + +# Allow using more than default advertising event length +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=251 + +# To present the audio at the right point in time, we need the controller and +# audio clock to be synchronized +CONFIG_MPSL_TRIGGER_IPC_TASK_ON_RTC_START=y +CONFIG_MPSL_TRIGGER_IPC_TASK_ON_RTC_START_CHANNEL=4 + +# General +CONFIG_DEBUG=n +CONFIG_ASSERT=n +CONFIG_STACK_USAGE=n +CONFIG_THREAD_MONITOR=n +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_PRINTK=n +CONFIG_UART_CONSOLE=n +CONFIG_BOOT_BANNER=n diff --git a/applications/nrf5340_audio/dfu/conf/Kconfig.dfu b/applications/nrf5340_audio/dfu/conf/Kconfig.dfu index 51e3769547f..2b11beb417d 100644 --- a/applications/nrf5340_audio/dfu/conf/Kconfig.dfu +++ b/applications/nrf5340_audio/dfu/conf/Kconfig.dfu @@ -21,11 +21,6 @@ config B0N_MINIMAL if AUDIO_DFU = 1 || AUDIO_DFU = 2 -# Empty net core image is needed when DFU is enabled -config NCS_SAMPLE_EMPTY_NET_CORE_CHILD_IMAGE - bool "Dummy Net core application" - default y - config AUDIO_DFU_ENABLE bool default y diff --git a/applications/nrf5340_audio/doc/adapting_application.rst b/applications/nrf5340_audio/doc/adapting_application.rst index d31478b02fe..8317f32ca74 100644 --- a/applications/nrf5340_audio/doc/adapting_application.rst +++ b/applications/nrf5340_audio/doc/adapting_application.rst @@ -1,18 +1,18 @@ .. _nrf53_audio_app_adapting: -Adapting nRF5340 Audio application for end products -################################################### +Adapting nRF5340 Audio applications for end products +#################################################### .. contents:: :local: :depth: 2 -This page describes the relevant configuration sources and lists the steps required for adapting the :ref:`nrf53_audio_app` application to end products. +This page describes the relevant configuration sources and lists the steps required for adapting the :ref:`nrf53_audio_app` to end products. Board configuration sources *************************** -The nRF5340 Audio application uses the following files as board configuration sources: +The nRF5340 Audio applications use the following files as board configuration sources: * Devicetree Specification (DTS) files - These reflect the hardware configuration. See :ref:`zephyr:dt-guide` for more information about the DTS data structure. @@ -30,7 +30,7 @@ For detailed instructions for adding Zephyr support to a custom board, see Zephy Application configuration sources ********************************* -The application configuration source file defines a set of options used by the nRF5340 Audio application. +The application configuration source file defines a set of options used by the given nRF5340 Audio application. This is a :file:`.conf` file that modifies the default Kconfig values defined in the Kconfig files. Only one :file:`.conf` file is included at a time. @@ -38,7 +38,7 @@ The :file:`prj.conf` file is the default configuration file and it implements th For the release application version, you need to include the :file:`prj_release.conf` configuration file. In the release application version no debug features should be enabled. -The nRF5340 Audio application also use several :file:`Kconfig.defaults` files to change configuration defaults automatically, based on the different application versions and device types. +Each nRF5340 Audio application also uses its own :file:`Kconfig.default` file to change configuration defaults automatically. You need to edit :file:`prj.conf` and :file:`prj_release.conf` if you want to add new functionalities to your application, but editing these files when adding a new board is not required. diff --git a/applications/nrf5340_audio/doc/building.rst b/applications/nrf5340_audio/doc/building.rst new file mode 100644 index 00000000000..8c85c4d01c6 --- /dev/null +++ b/applications/nrf5340_audio/doc/building.rst @@ -0,0 +1,249 @@ +.. _nrf53_audio_app_building: + +Building and running nRF5340 Audio applications +############################################### + +.. contents:: + :local: + :depth: 2 + +This nRF5340 Audio application source files can be found in their respective folders under :file:`applications/nrf5340_audio` in the nRF Connect SDK folder structure. + +You can build and program the applications in one of the following ways: + +* :ref:`nrf53_audio_app_building_script`. + This is the suggested method. + Using this method allows you to build and program multiple development kits at the same time. +* :ref:`nrf53_audio_app_building_standard`. + Using this method requires building and programming each development kit separately. + +.. important:: + Building and programming using the |nRFVSC| is currently not supported. + +.. note:: + You might want to check the :ref:`nRF5340 Audio application known issues ` before building and programming the applications. + +.. _nrf53_audio_app_dk_testing_out_of_the_box: + +Testing out of the box +********************** + +Each development kit comes preprogrammed with basic firmware that indicates if the kit is functional. +Before building the application, you can verify if the kit is working by completing the following steps: + +1. Plug the device into the USB port. +#. Turn on the development kit using the On/Off switch. +#. Observe **RGB** (bottom side LEDs around the center opening that illuminate the Nordic Semiconductor logo) turn solid yellow, **OB/EXT** turn solid green, and **LED3** start blinking green. + +You can now program the development kit. + +.. _nrf53_audio_app_building_script: + +Building and programming using script +************************************* + +The suggested method for building each of the applications and programming it to the development kit is running the :file:`buildprog.py` Python script, which is located in the :file:`applications/nrf5340_audio/tools/buildprog` directory. +The script automates the process of selecting :ref:`configuration files ` and building different applications. +This eases the process of building and programming images for multiple development kits. + +Preparing the JSON file +======================= + +The script depends on the settings defined in the :file:`nrf5340_audio_dk_devices.json` file. +Before using the script, make sure to update this file with the following information for each development kit you want to use: + +* ``nrf5340_audio_dk_snr`` -- This field lists the SEGGER serial number. + You can check this number on the sticker on the nRF5340 Audio development kit. + Alternatively, connect the development kit to your PC and run ``nrfjprog -i`` in a command window to print the SEGGER serial number of the kit. +* ``nrf5340_audio_dk_dev`` -- This field assigns the specific nRF5340 Audio development kit to be ``headset`` or ``gateway``. +* ``channel`` -- This field is valid only for headsets. + It sets the channels on which the headset is meant to work. + When no channel is set, the headset is programmed as a left channel one. + +.. _nrf53_audio_app_building_script_running: + +Running the script +================== + +After editing the :file:`nrf5340_audio_dk_devices.json` file, run :file:`buildprog.py` to build the firmware for the development kits. +The building command for running the script requires providing the following parameters: + +* Core type (``-c`` parameter): ``app``, ``net``, or ``both`` +* Application version (``-b`` parameter): either ``release`` or ``debug`` +* Device type (``-d`` parameter): ``headset``, ``gateway``, or ``both`` +* DFU type (``-m`` parameter): ``internal``, ``external`` +* Network core bootloader minimal size (``-M``) + +See the following examples of the parameter usage with the command run from the :file:`buildprog` directory: + +* Example 1: The following command builds headset and gateway applications using the script for the application core with the ``debug`` application version: + + .. code-block:: console + + python buildprog.py -c app -b debug -d both + +* Example 2: The following command builds headset and gateway applications using the script for both the application and the network core (``both``). + It builds with the ``release`` application version, with the DFU external flash memory layout enabled, and using the minimal size of the network core bootloader: + + .. code-block:: console + + python buildprog.py -c both -b release -d both -m external -M + +The command can be run from any location, as long as the correct path to :file:`buildprog.py` is given. + +The build files are saved in the :file:`applications/nrf5340_audio/build` directory. +The script creates a directory for each application version and device type combination. +For example, when running the command above, the script creates the :file:`dev_gateway/build_debug` and :file:`dev_headset/build_debug` directories. + +Programming with the script + The development kits are programmed according to the serial numbers set in the JSON file. + Make sure to connect the development kits to your PC using USB and turn them on using the **POWER** switch before you run the command. + + The following parameters are available for programming: + + * Programming (``-p`` parameter) -- If you run the building script with this parameter, you can program one or both of the cores after building the files. + * Sequential programming (``-s`` parameter) -- If you encounter problems while programming, include this parameter alongside other parameters to program sequentially. + + The command for programming can look as follows: + + .. code-block:: console + + python buildprog.py -c both -b debug -d both -p + + This command builds the headset and the gateway applications with ``debug`` version of both the application core binary and the network core binary - and programs each to its respective core. + + .. note:: + If the programming command fails because of :ref:`readback_protection_error`, run :file:`buildprog.py` with the ``--recover_on_fail`` or ``-f`` parameter to recover and re-program automatically when programming fails. + For example, using the programming command example above: + + .. code-block:: console + + python buildprog.py -c both -b debug -d both -p --recover_on_fail + + If you want to program firmware that has DFU enabled, you must include the DFU parameters in the command. + The command for programming with DFU enabled can look as follows: + + .. code-block:: console + + python buildprog.py -c both -b release -d both -m external -M -p + +Getting help + Run ``python buildprog.py -h`` for information about all available script parameters. + +Configuration table overview + When running the script command, a table similar to the following one is displayed to provide an overview of the selected options and parameter values: + + .. code-block:: console + + +------------+----------+---------+--------------+---------------------+---------------------+ + | snr | snr conn | device | only reboot | core app programmed | core net programmed | + +------------+----------+---------+--------------+---------------------+---------------------+ + | 1010101010 | True | headset | Not selected | Selected TBD | Not selected | + | 2020202020 | True | gateway | Not selected | Selected TBD | Not selected | + | 3030303030 | True | headset | Not selected | Selected TBD | Not selected | + +------------+----------+---------+--------------+---------------------+---------------------+ + + See the following table for the meaning of each column and the list of possible values: + + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + | Column | Indication | Possible values | + +=======================+=====================================================================================================+=================================================+ + | ``snr`` | Serial number of the device, as provided in the :file:`nrf5340_audio_dk_devices.json` file. | Serial number. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + | ``snr conn`` | Whether the device with the provided serial number is connected to the PC with a serial connection. | ``True`` - Connected. | + | | +-------------------------------------------------+ + | | | ``False`` - Not connected. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + | ``device`` | Device type, as provided in the :file:`nrf5340_audio_dk_devices.json` file. | ``headset`` - Headset. | + | | +-------------------------------------------------+ + | | | ``gateway`` - Gateway. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + | ``only reboot`` | Whether the device is to be only reset and not programmed. | ``Not selected`` - No reset. | + | | This depends on the ``-r`` parameter in the command, which overrides other parameters. +-------------------------------------------------+ + | | | ``Selected TBD`` - Only reset requested. | + | | +-------------------------------------------------+ + | | | ``Done`` - Reset done. | + | | +-------------------------------------------------+ + | | | ``Failed`` - Reset failed. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + |``core app programmed``| Whether the application core is to be programmed. | ``Not selected`` - Core will not be programmed. | + | | This depends on the value provided to the ``-c`` parameter (see above). +-------------------------------------------------+ + | | | ``Selected TBD`` - Programming requested. | + | | +-------------------------------------------------+ + | | | ``Done`` - Programming done. | + | | +-------------------------------------------------+ + | | | ``Failed`` - Programming failed. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + |``core net programmed``| Whether the network core is to be programmed. | ``Not selected`` - Core will not be programmed. | + | | This depends on the value provided to the ``-c`` parameter (see above). +-------------------------------------------------+ + | | | ``Selected TBD`` - Programming requested. | + | | +-------------------------------------------------+ + | | | ``Done`` - Programming done. | + | | +-------------------------------------------------+ + | | | ``Failed`` - Programming failed. | + +-----------------------+-----------------------------------------------------------------------------------------------------+-------------------------------------------------+ + +.. _nrf53_audio_app_building_standard: + +Building and programming using command line +******************************************* + +You can also build the nRF5340 Audio applications using the standard |NCS| :ref:`build steps ` for the command line. + +.. note:: + Using this method requires you to build and program each development kit one at a time before moving to the next configuration, which can be time-consuming. + :ref:`nrf53_audio_app_building_script` is recommended. + +Building the application +======================== + +Complete the following steps to build the application: + +1. Choose the combination of build flags: + + a. Choose the device type by using one of the following options: + + * For headset device: ``-DCONFIG_AUDIO_DEV=1`` + * For gateway device: ``-DCONFIG_AUDIO_DEV=2`` + + #. Choose the application version by using one of the following options: + + * For the debug version: No build flag needed. + * For the release version: ``-DFILE_SUFFIX=release`` + +#. Build the application using the standard :ref:`build steps ` for the command line. + For example, if you want to build the firmware for the application core as a headset using the ``release`` application version, you can run the following command from the :file:`applications/nrf5340_audio/` directory: + + .. code-block:: console + + west build -b nrf5340_audio_dk_nrf5340_cpuapp --pristine -- -DCONFIG_AUDIO_DEV=1 -DFILE_SUFFIX=release + + Unlike when :ref:`nrf53_audio_app_building_script`, this command creates the build files directly in the :file:`build` directory. + This means that you first need to program the headset development kits before you build and program gateway development kits. + Alternatively, you can add the ``-d`` parameter to the ``west`` command to specify a custom build folder. This lets you build firmware for both + headset and gateway before programming any development kits. + +Programming the application +=========================== + +After building the files for the development kit you want to program, follow the :ref:`standard procedure for programming applications ` in the |NCS|. + +When using the default CIS configuration, if you want to use two headset devices, you must also populate the UICR with the desired channel for each headset. +Use the following commands, depending on which headset you want to populate: + +* Left headset: + + .. code-block:: console + + nrfjprog --memwr 0x00FF80F4 --val 0 + +* Right headset: + + .. code-block:: console + + nrfjprog --memwr 0x00FF80F4 --val 1 + +Select the correct board when prompted with the popup or add the ``--snr`` parameter followed by the SEGGER serial number of the correct board at the end of the ``nrfjprog`` command. + +.. note:: + |usb_known_issues| diff --git a/applications/nrf5340_audio/doc/configuration.rst b/applications/nrf5340_audio/doc/configuration.rst new file mode 100644 index 00000000000..f18ceca73fb --- /dev/null +++ b/applications/nrf5340_audio/doc/configuration.rst @@ -0,0 +1,83 @@ +.. _nrf53_audio_app_configuration: + +Configuring the nRF5340 Audio applications +########################################## + +.. contents:: + :local: + :depth: 2 + +|config| + +.. _nrf53_audio_app_configuration_select_bidirectional: + +Selecting the CIS bidirectional communication +********************************************* + +By default, if you have not made any changes to :file:`.conf` files at :file:`applications/nrf5340_audio/`, the nRF5340 build script tries to build the CIS applications in the CIS unidirectional mode. +To switch to the bidirectional mode, set the ``CONFIG_STREAM_BIDIRECTIONAL`` Kconfig option to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file (for the debug version) or in the :file:`applications/nrf5340_audio/prj_release.conf` file (for the release version). + +.. _nrf53_audio_app_configuration_enable_walkie_talkie: + +Enabling the walkie-talkie demo +=============================== + +The walkie-talkie demo uses one or two bidirectional streams from the gateway to one or two headsets. +The PDM microphone is used as input on both the gateway and headset device. +To switch to using the walkie-talkie, set the ``CONFIG_WALKIE_TALKIE_DEMO`` Kconfig option to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file (for the debug version) or in the :file:`applications/nrf5340_audio/prj_release.conf` file (for the release version). + +.. _nrf53_audio_app_configuration_select_bis_two_gateways: + +Enabling the BIS mode with two gateways +*************************************** + +In addition to the standard BIS mode with one gateway, you can also add a second gateway device. +The BIS headsets can then switch between the two gateways and receive audio stream from one of the two gateways. + +To configure the second gateway, add both the ``CONFIG_TRANSPORT_BIS`` and the ``CONFIG_BT_AUDIO_USE_BROADCAST_NAME_ALT`` Kconfig options set to ``y`` to the :file:`applications/nrf5340_audio/prj.conf` file for the debug version and to the :file:`applications/nrf5340_audio/prj_release.conf` file for the release version. +You can provide an alternative name to the second gateway using the ``CONFIG_BT_AUDIO_BROADCAST_NAME_ALT`` or use the default alternative name. + +You build each BIS gateway separately using the normal procedures from :ref:`nrf53_audio_app_building`. +After building the first gateway, configure the required Kconfig options for the second gateway and build the second gateway firmware. +Remember to program the two firmware versions to two separate gateway devices. + +.. _nrf53_audio_app_configuration_select_i2s: + +Selecting the analog jack input using I2S +***************************************** + +In the default configuration, the gateway application uses USB as the audio source. +The :ref:`nrf53_audio_app_building` and the testing steps also refer to using the USB serial connection. + +To switch to using the 3.5 mm jack analog input, set the ``CONFIG_AUDIO_SOURCE_I2S`` Kconfig option to ``y`` in the :file:`applications/nrf5340_audio/prj.conf` file for the debug version and in the :file:`applications/nrf5340_audio/prj_release.conf` file for the release version. + +When testing the application, an additional audio jack cable is required to use I2S. +Use this cable to connect the audio source (PC) to the analog **LINE IN** on the development kit. + +.. _nrf53_audio_app_adding_FEM_support: + +Adding FEM support +****************** + +You can add support for the nRF21540 front-end module (FEM) to the following nRF5340 Audio applications: + +* :ref:`Broadcast source ` +* :ref:`Unicast client ` +* :ref:`Unicast server ` + +The :ref:`broadcast sink application ` does not need FEM support as it only receives data. + +Adding FEM support happens when :ref:`nrf53_audio_app_building`. +You can use one of the following options, depending on how you decide to build the application: + +* If you opt for :ref:`nrf53_audio_app_building_script`, add the ``--nrf21540`` to the script's building command. +* If you opt for :ref:`nrf53_audio_app_building_standard`, add the ``-DSHIELD=nrf21540ek_fwd`` to the ``west build`` command. + For example: + + .. code-block:: console + + west build -b nrf5340_audio_dk_nrf5340_cpuapp --pristine -- -DCONFIG_AUDIO_DEV=1 -DSHIELD=nrf21540ek_fwd -DFILE_SUFFIX=release + +To set the TX power output, use the ``CONFIG_NRF_21540_MAIN_TX_POWER`` and ``CONFIG_NRF_21540_PRI_ADV_TX_POWER`` Kconfig options. + +See :ref:`ug_radio_fem` for more information about FEM in the |NCS|. diff --git a/applications/nrf5340_audio/doc/feature_support.rst b/applications/nrf5340_audio/doc/feature_support.rst index 5a46ade2bce..45d22ad8b83 100644 --- a/applications/nrf5340_audio/doc/feature_support.rst +++ b/applications/nrf5340_audio/doc/feature_support.rst @@ -27,7 +27,3 @@ The following QDIDs are related to the nRF5340 Audio application: :docset: nrfxlib :start-after: lc3_qdid_start :end-before: lc3_qdid_end - -.. include:: /libraries/bin/bt_ll_acs_nrf53/index.rst - :start-after: le_audio_controller_qdid_start - :end-before: le_audio_controller_qdid_end diff --git a/applications/nrf5340_audio/doc/firmware_architecture.rst b/applications/nrf5340_audio/doc/firmware_architecture.rst index ba010dc2e82..dd237a2f064 100644 --- a/applications/nrf5340_audio/doc/firmware_architecture.rst +++ b/applications/nrf5340_audio/doc/firmware_architecture.rst @@ -7,50 +7,26 @@ nRF5340 Audio overview and firmware architecture :local: :depth: 2 -The application can work as a gateway or a headset. -The gateway receives the audio data from external sources (USB or I2S) and forwards it to one or more headsets. -The headset is a receiver device that plays back the audio it gets from the gateway. -It is also possible to enable a bidirectional mode where one gateway can send and receive audio to and from one or two headsets at the same time. +Each nRF5340 Audio application corresponds to one specific LE Audio role: unicast client (gateway), unicast server (headset), broadcast source (gateway), or broadcast sink (headset). +The gateway receives the audio data from external sources (USB or line input/I2S) and forwards it to one or more headsets. +The headset is a receiver device that plays back the audio it gets from the gateway, and will act as earbuds, headphones, a speaker, hearing aids, or similar. -Both device types use the same code base, but different firmware, and you need both types of devices for testing the application. -Gateways and headsets can both run in one of the available application modes, either the *connected isochronous stream* (CIS) mode or in the *broadcast isochronous stream* (BIS) mode. -The CIS mode is the default mode of the application. +Each nRF5340 Audio application is configured for one specific LE Audio mode: the *connected isochronous stream* (CIS, unicast) mode or in the *broadcast isochronous stream* (BIS) mode. +See :ref:`nrf53_audio_app_overview_modes` for more information. -Changing configuration related to the device type and the application modes requires rebuilding the firmware and reprogramming the development kits. +The applications use the same code base, but use different :file:`main.c` files and include different modules and libraries depending on the configuration. -Regardless of the configuration, the application handles the audio data in the following manner: - -1. The gateway receives audio data from the audio source over USB or I2S. -#. The gateway processes the audio data in its application core, which channels the data through the application layers: - - a. Audio data is sent to the synchronization module (I2S-based firmware) or directly to the software codec (USB-based firmware). - #. Audio data is encoded by the software codec. - #. Encoded audio data is sent to the Bluetooth LE Host. - -#. The host sends the encoded audio data to the LE Audio Controller Subsystem for nRF53 on the network core. -#. The subsystem forwards the audio data to the hardware radio and sends it to the headset devices, as per the LE Audio specifications. -#. The headsets receive the encoded audio data on their hardware radio on the network core side. -#. The LE Audio Controller Subsystem for nRF53 running on each of the headsets sends the encoded audio data to the Bluetooth LE Host on the headsets' application core. -#. The headsets process the audio data in their application cores, which channel the data through the application layers: - - a. Audio data is sent to the stream control module and placed in a FIFO buffer. - #. Audio data is sent from the FIFO buffer to the synchronization module (headsets only use I2S-based firmware). - #. Audio data is decoded by the software codec. - -#. Decoded audio data is sent to the hardware audio output over I2S. - -In the `I2S-based firmware for gateway and headsets`_, sending the audio data through the application layers includes a mandatory synchronization step using the synchronization module. -This proprietary module ensures that the audio is played at the same time with the correct speed. -For more information, see `Synchronization module overview`_. +You might need to configure and program two applications for testing the interoperability, depending on your use case. +See the testing steps for each of the application for more information. .. _nrf53_audio_app_overview_modes: Application modes ***************** -The application can work either in the *connected isochronous stream* (CIS) mode or in the *broadcast isochronous stream* (BIS) mode, depending on the chosen firmware configuration. +Each application works either in the *connected isochronous stream* (CIS) mode or in the *broadcast isochronous stream* (BIS) mode. -.. figure:: /images/octave_application_topologies.svg +.. figure:: /images/nrf5340_audio_application_topologies.png :alt: CIS and BIS mode overview CIS and BIS mode overview @@ -59,10 +35,10 @@ Connected Isochronous Stream (CIS) CIS is a bidirectional communication protocol that allows for sending separate connected audio streams from a source device to one or more receivers. The gateway can send the audio data using both the left and the right ISO channels at the same time, allowing for stereophonic sound reproduction with synchronized playback. - This is the default configuration of the nRF5340 Audio application. - In this configuration, you can use the nRF5340 Audio development kit in the role of the gateway, the left headset, or the right headset. + This is the mode available for the unicast applications (:ref:`unicast client` and :ref:`unicast server`). + In this mode, you can use the nRF5340 Audio development kit in the role of the gateway, the left headset, or the right headset. - In the current version of the nRF5340 Audio application, the CIS mode offers both unidirectional and bidirectional communication. + In the current version of the nRF5340 Audio unicast client, the application offers both unidirectional and bidirectional communication. In the bidirectional communication, the headset device will send audio from the on-board PDM microphone. See :ref:`nrf53_audio_app_configuration_select_bidirectional` in the application description for more information. @@ -73,7 +49,8 @@ Connected Isochronous Stream (CIS) Broadcast Isochronous Stream (BIS) BIS is a unidirectional communication protocol that allows for broadcasting one or more audio streams from a source device to an unlimited number of receivers that are not connected to the source. - In this configuration, you can use the nRF5340 Audio development kit in the role of the gateway or as one of the headsets. + This is the mode available for the broadcast applications (:ref:`broadcast source` for headset and :ref:`broadcast sink` for gateway). + In this mode, you can use the nRF5340 Audio development kit in the role of the gateway or as one of the headsets. Use multiple nRF5340 Audio development kits to test BIS having multiple receiving headsets. .. note:: @@ -88,15 +65,14 @@ Firmware architecture The following figure illustrates the software layout for the nRF5340 Audio application: -.. figure:: /images/octave_application_structure_generic.svg +.. figure:: /images/nrf5340_audio_structure_generic.svg :alt: nRF5340 Audio high-level design (overview) nRF5340 Audio high-level design (overview) -The network core of the nRF5340 SoC runs the *LE Audio Controller Subsystem for nRF53*, which is included in the :ref:`lib_bt_ll_acs_nrf53_readme` library's HEX file. -This subsystem is custom-made for the application. -It is responsible for receiving the audio stream data from hardware layers and forwarding the data to the Bluetooth LE host on the application core. -The subsystem implements the lower layers of the Bluetooth Low Energy software stack and follows the LE Audio specification requirements. +The network core of the nRF5340 SoC runs the SoftDevice Controller, which is responsible for receiving the audio stream data from hardware layers and forwarding the data to the Bluetooth LE host on the application core. +The controller implements the lower layers of the Bluetooth Low Energy software stack. +See :ref:`ug_ble_controller_softdevice` for more information about the controller, and :ref:`SoftDevice Controller for LE Isochronous Channels ` for information on how it implements ISO channels used by the nRF5340 Audio applications. The application core runs both the Bluetooth LE Host from Zephyr and the application layer. The application layer is composed of a series of modules from different sources. @@ -120,73 +96,86 @@ These modules include the following major ones: * Renderer - This module handles rendering, such as volume up and down. * Content Control - This module handles content control, such as play and pause. -* Application-specific custom modules: - - * Stream Control - This module handles events from the Bluetooth modules and buttons, receives audio from one module, and forwards the audio data to the next module. - - * Currently, each of the four main device types uses a separate stream control file: - - * CIS gateway (unicast client) - :file:`streamctrl_unicast_client.c` - * CIS headset (unicast server) - :file:`streamctrl_unicast_server.c` - * BIS gateway (broadcast source) - :file:`streamctrl_broadcast_source.c` - * BIS headset (broadcast sink) - :file:`streamctrl_broadcast_sink.c` +* Application-specific custom modules, including the synchronization module (part of `I2S-based firmware for gateway and headsets`_) - See `Synchronization module overview`_ for more information. - * FIFO buffers - * Synchronization module (part of `I2S-based firmware for gateway and headsets`_) - See `Synchronization module overview`_ for more information. - -Since the application architecture is uniform and the firmware code is shared, the set of audio modules in use depends on the chosen stream mode (BIS or CIS), the chosen audio inputs and outputs (USB or analog jack), and if the gateway or the headset configuration is selected. +Since the application architecture is the same for all applications and the code before compilation is shared to a significant degree, the set of modules in use depends on the chosen audio inputs and outputs (USB or analog jack). .. note:: - In the current version of the application, the bootloader is disabled by default. + In the current versions of the applications, the bootloader is disabled by default. Device Firmware Update (DFU) can only be enabled when :ref:`nrf53_audio_app_building_script`. See :ref:`nrf53_audio_app_configuration_configure_fota` for details. -Communications between modules -============================== - -Communication between modules is primarily done through Zephyr's :ref:`zephyr:zbus` to make sure that there are as few dependencies as possible. Each of the buses used by the application has their message structures described in :file:`nrf5340_audio_common.h`. - -The application uses the following buses: +Communication between modules +============================= - * ``le_audio_chan`` - For handling LE Audio events from the Bluetooth stream modules, specifically :file:`unicast_client.c`, :file:`unicast_server.c`, :file:`broadcast_source.c`, and :file:`broadcast_sink.c`. - * ``button_chan`` - For handling button events from :file:`button_handler.c`. - * ``bt_mgmt_chan`` - For handling ACL events from :file:`bt_mgmt.c`. - * ``volume_chan`` - For handling volume events from :file:`bt_rend.c`. - * ``cont_media_chan`` - For handling media events from :file:`content_ctrl.c`. - -The consumer functions for each of these buses are residing, for the most part, in the stream control files. -``volume_chan`` is an exception, with its consumer functions residing directly in :file:`hw_codec.c`. -The linking of producers and consumers is done in the stream control files. +Communication between modules is primarily done through Zephyr's :ref:`zephyr:zbus` to make sure that there are as few dependencies as possible. Each of the buses used by the applications has their message structures described in :file:`nrf5340_audio_common.h`. .. _nrf53_audio_app_overview_architecture_usb: USB-based firmware for gateway ============================== -The following figure shows an overview of the modules currently included in the firmware that uses USB: - -.. figure:: /images/octave_application_structure_gateway.svg - :alt: nRF5340 Audio modules on the gateway using USB - - nRF5340 Audio modules on the gateway using USB +The following figures show an overview of the modules currently included in the firmware of applications that use USB. In this firmware design, no synchronization module is used after decoding the incoming frames or before encoding the outgoing ones. The Bluetooth LE RX FIFO is mainly used to make decoding run in a separate thread. +Broadcast source USB-based firmware +----------------------------------- + +.. figure:: /images/nrf5340_audio_broadcast_source_USB_structure.svg + :alt: nRF5340 Audio modules for the broadcast source using USB + + nRF5340 Audio modules for the broadcast source using USB + +Unicast client USB-based firmware +--------------------------------- + +.. figure:: /images/nrf5340_audio_unicast_client_USB_structure.svg + :alt: nRF5340 Audio modules for the unicast client using USB + + nRF5340 Audio modules for the unicast client using USB + .. _nrf53_audio_app_overview_architecture_i2s: I2S-based firmware for gateway and headsets =========================================== -The following figure shows an overview of the modules currently included in the firmware that uses I2S: +The following figure shows an overview of the modules currently included in the firmware of applications that use I2S. -.. figure:: /images/octave_application_structure.svg - :alt: nRF5340 Audio modules on the gateway and the headsets using I2S +The Bluetooth LE RX FIFO is mainly used to make :file:`audio_datapath.c` (synchronization module) run in a separate thread. - nRF5340 Audio modules on the gateway and the headsets using I2S +Broadcast source I2S-based firmware +----------------------------------- -The Bluetooth LE RX FIFO is mainly used to make :file:`audio_datapath.c` (synchronization module) run in a separate thread. -After encoding the audio data received from I2S, the frames are sent by the encoder thread using a function located in :file:`streamctrl_unicast_client.c`, :file:`streamctrl_unicast_server.c`, :file:`streamctrl_broadcast_source.c`, or :file:`streamctrl_broadcast_sink.c`. +.. figure:: /images/nrf5340_audio_broadcast_source_I2S_structure.svg + :alt: nRF5340 Audio modules for the broadcast source using I2S + + nRF5340 Audio modules for the broadcast source using I2S + +Broadcast sink I2S-based firmware +--------------------------------- + +.. figure:: /images/nrf5340_audio_broadcast_sink_I2S_structure.svg + :alt: nRF5340 Audio modules for the broadcast sink using I2S + + nRF5340 Audio modules for the broadcast sink using I2S + +Unicast client I2S-based firmware +--------------------------------- + +.. figure:: /images/nrf5340_audio_unicast_client_I2S_structure.svg + :alt: nRF5340 Audio modules for the unicast client using I2S + + nRF5340 Audio modules for the unicast client using I2S + +Unicast server I2S-based firmware +--------------------------------- + +.. figure:: /images/nrf5340_audio_unicast_server_I2S_structure.svg + :alt: nRF5340 Audio modules for the unicast server using I2S + + nRF5340 Audio modules for the unicast server using I2S .. _nrf53_audio_app_overview_architecture_sync_module: @@ -213,7 +202,7 @@ This prevents I2S overruns or underruns, both in the CIS mode and the BIS mode. See the following figure for an overview of the synchronization module. -.. figure:: /images/octave_application_structure_sync_module.svg +.. figure:: /images/nrf5340_audio_structure_sync_module.svg :alt: nRF5340 Audio synchronization module overview nRF5340 Audio synchronization module overview @@ -238,7 +227,7 @@ These blocks are then continuously being fed to I2S, block by block. See the following figure for the details of the compensation methods of the synchronization module. -.. figure:: /images/octave_application_sync_module_states.svg +.. figure:: /images/nrf5340_audio_sync_module_states.svg :alt: nRF5340 Audio's state machine for compensation mechanisms nRF5340 Audio's state machine for compensation mechanisms @@ -262,14 +251,14 @@ Synchronization module flow The received audio data in the I2S-based firmware devices follows the following path: -1. The LE Audio Controller Subsystem for nRF53 running on the network core receives the compressed audio data. -#. The controller subsystem sends the audio data to the Zephyr Bluetooth LE host similarly to the :ref:`zephyr:bluetooth-hci-ipc-sample` sample. +1. The SoftDevice Controller running on the network core receives the compressed audio data. +#. The controller, running in the :ref:`zephyr:bluetooth-hci-ipc-sample` sample on the nRF5340 SoC network core, sends the audio data to the Zephyr Bluetooth LE host running on the nRF5340 SoC application core. #. The host sends the data to the stream control module. #. The data is sent to a FIFO buffer. #. The data is sent from the FIFO buffer to the :file:`audio_datapath.c` synchronization module. The :file:`audio_datapath.c` module performs the audio synchronization based on the SDU reference timestamps. Each package sent from the gateway gets a unique SDU reference timestamp. - These timestamps are generated on the headset controllers (in the network core). + These timestamps are generated on the headset Bluetooth LE controller (in the network core). This enables the creation of True Wireless Stereo (TWS) earbuds where the audio is synchronized in the CIS mode. It does also keep the speed of the inter-IC sound (I2S) interface synchronized with the sending and receiving speed of Bluetooth packets. #. The :file:`audio_datapath.c` module sends the compressed audio data to the LC3 audio decoder for decoding. diff --git a/applications/nrf5340_audio/doc/fota.rst b/applications/nrf5340_audio/doc/fota.rst new file mode 100644 index 00000000000..fb42294581c --- /dev/null +++ b/applications/nrf5340_audio/doc/fota.rst @@ -0,0 +1,72 @@ +.. _nrf53_audio_app_fota: + +Configuring and testing FOTA upgrades for nRF5340 Audio applications +#################################################################### + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio applications all support FOTA upgrades, and the application implementation is based on the procedure described in :ref:`ug_nrf53_developing_ble_fota`. + +Requirements for FOTA +********************* + +If the application is running on the nRF5340 Audio DK, you need an external flash shield to upgrade both the application and network core at the same time. +See `Requirements for external flash memory DFU`_ in the nRF5340 Audio DK Hardware documentation for more information. + +.. _nrf53_audio_app_configuration_configure_fota: + +Configuring FOTA upgrades +************************* + +The nRF5340 Audio application supports two strategies for upgrading the applications on the application and network core: single-image and multi-image. +You control which of the two strategies is used by setting the Kconfig :kconfig:option:`CONFIG_AUDIO_DFU` to the appropriate setting. + +* Single-image upgrade - Uses the internal flash to upgrade either the application core or network core separately. + You can select this method by setting :kconfig:option:`CONFIG_AUDIO_DFU` to ``1``. +* Multi-image upgrade - Uses external flash to upgrade both the application and network core at the same time. + You can select this method by setting :kconfig:option:`CONFIG_AUDIO_DFU` to ``2``. + See :ref:`multi-image DFU ` for more information about the process. + +.. caution:: + Using the single-image upgrade strategy carries risk of the device being in a state where the application core firmware and network core firmware are no longer compatible, which can result in a bricked device. + For devices where FOTA is the only DFU method available, multi-image upgrades are recommended to ensure compatibility between the cores. + Make sure to evaluate the risks for your device when selecting the FOTA method. + +Updating the SoftDevice +======================= + +Both FOTA upgrade methods support updating the SoftDevice on the network core. +However, the current default build options for the SoftDevice create a binary that is too large to run on the network core together with a bootloader. +To reduce the size of the SoftDevice binary, you can disable unused features in the SoftDevice. +See :ref:`softdevice_controller` documentation for more information. + +Entering the DFU mode +===================== + +The |NCS| uses :ref:`SMP server and mcumgr ` as the DFU backend. +The SMP server service is separated from CIS and BIS services, and is only advertised when the application is in the DFU mode. +To enter the DFU mode, press **BTN 4** on the nRF5340 Audio DK during startup. + +To identify the devices before the DFU takes place, the DFU mode advertising names mention the device type directly. +The names follow the pattern in which the device role is inserted between the device name and the ``_DFU`` suffix. +For example: + +* Gateway: ``NRF5340_AUDIO_GW_DFU`` +* Left Headset: ``NRF5340_AUDIO_HL_DFU`` +* Right Headset: ``NRF5340_AUDIO_HR_DFU`` + +The first part of these names is based on :kconfig:option:`CONFIG_BT_DEVICE_NAME`. + +.. note:: + When performing DFU for the nRF5340 Audio applications, there will be one or more error prints related to opening flash area ID 1. + This is due to restrictions in the DFU system, and the error print is expected. + The DFU process should still complete successfully. + +.. _nrf53_audio_unicast_client_app_testing_steps_fota: + +Testing FOTA upgrades +===================== + +To test FOTA for the nRF5340 Audio application, ensure the application is in the DFU mode, and then follow the testing steps in the FOTA over Bluetooth Low Energy section of :ref:`ug_nrf53_developing_ble_fota` (you can skip the configuration steps). diff --git a/applications/nrf5340_audio/doc/index.rst b/applications/nrf5340_audio/doc/index.rst deleted file mode 100644 index ffb0eaf8148..00000000000 --- a/applications/nrf5340_audio/doc/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _nrf53_audio_app: - -nRF5340 Audio -############# - -.. contents:: - :local: - :depth: 2 - -The nRF5340 Audio application demonstrates audio playback over isochronous channels (ISO) using LC3 codec compression and decompression, as per `Bluetooth® LE Audio specifications`_. - -.. note:: - There is an ongoing process of restructuring the nRF5340 Audio application project. - Several drivers and modules within the application folder are being moved to more suitable locations in the |NCS| or Zephyr. - Before this process has finished, developing out-of-tree applications can be more complex. - -.. note:: - This application and its DFU/FOTA functionality are marked as :ref:`experimental `. - -See the subpages for detailed documentation on the application and its internal modules: - -.. _nrf53_audio_app_subpages: - -.. toctree:: - :maxdepth: 1 - :caption: Subpages: - - firmware_architecture - feature_support - ../README - adapting_application diff --git a/applications/nrf5340_audio/doc/requirements.rst b/applications/nrf5340_audio/doc/requirements.rst new file mode 100644 index 00000000000..1043b801e92 --- /dev/null +++ b/applications/nrf5340_audio/doc/requirements.rst @@ -0,0 +1,65 @@ +.. _nrf53_audio_app_requirements: + +nRF5340 Audio application requirements +###################################### + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio applications are designed to be used only with the following hardware: + +.. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf5340_audio_dk_nrf5340 + +.. note:: + The applications supports PCA10121 revisions 1.0.0 or above. + The applications are also compatible with the following pre-launch revisions: + + * Revisions 0.8.0 and above. + +You need at least two nRF5340 Audio development kits (one with the gateway firmware and one with headset firmware) to test each of the applications. +For CIS with TWS in mind, three kits are required. + +If you want to test with other hardware (for example, a mobile phone or PC), it is highly recommended to test with Audio DKs on both the gateway and headset side first to verify basic functionality before moving on to testing with other vendors. + +.. _nrf53_audio_app_requirements_codec: + +Software codec requirements +*************************** + +The nRF5340 Audio applications only support the :ref:`LC3 software codec `, developed specifically for use with LE Audio. + +The applications can be configured for other alternative codecs, but this integration is beyond the scope of this documentation. + +.. _nrf53_audio_app_dk: +.. _nrf53_audio_app_dk_features: + +nRF5340 Audio development kit +***************************** + +The nRF5340 Audio development kit is a hardware development platform that demonstrates the nRF5340 Audio applications. +Read the `nRF5340 Audio DK Hardware`_ documentation on Nordic Semiconductor Infocenter for more information about this development kit. + +You can :ref:`test the DK out of the box ` before you program it. + +.. _nrf53_audio_app_configuration_files: + +nRF5340 Audio configuration files +********************************* + +All applications use the :file:`Kconfig.defaults` located in the :file:`nrf5340_audio` directory. +Additionally, each nRF5340 Audio application uses its own, application-specific :file:`Kconfig.defaults` file from the application directory, which includes configuration specific to the given application. +These files change the configuration defaults automatically, based on the different application versions and device types. + +For each application, only one of the following :file:`.conf` files is included when building: + +* :file:`prj.conf` is the default configuration file and it implements the debug application version. +* :file:`prj_release.conf` is the optional configuration file and it implements the release application version. + No debug features are enabled in the release application version. + When building using the command line, you must explicitly specify if :file:`prj_release.conf` is going to be included instead of :file:`prj.conf`. + See :ref:`nrf53_audio_app_building` for details. + +In addition, the application features the :file:`child_image` directory with :file:`hci_ipc.conf`. +This file contains the necessary configurations for nRF5340 Audio applications to run the :ref:`bluetooth-hci-ipc-sample` sample with :ref:`SoftDevice Controller for LE Isochronous Channels ` support. diff --git a/applications/nrf5340_audio/doc/user_interface.rst b/applications/nrf5340_audio/doc/user_interface.rst new file mode 100644 index 00000000000..387d0494b75 --- /dev/null +++ b/applications/nrf5340_audio/doc/user_interface.rst @@ -0,0 +1,160 @@ +.. _nrf53_audio_app_ui: + +User interface +############## + +.. contents:: + :local: + :depth: 2 + +All nRF5340 Audio applications implement the same, simple user interface based on the available PCB elements of the nRF5340 Audio development kit. +You can control the application using predefined switches and buttons while the LEDs display information. + +Some user interface options are only valid for some nRF5340 Audio applications. + +.. _nrf53_audio_app_ui_switches: + +Switches +******** + +The application uses the following switches on the supported development kit: + ++-------------------+-------------------------------------------------------------------------------------+---------------------------------------+ +| Switch | Function | Applications | ++===================+=====================================================================================+=======================================+ +| **POWER** | Turns the development kit on or off. | All | ++-------------------+-------------------------------------------------------------------------------------+---------------------------------------+ +| **DEBUG ENABLE** | Turns on or off power for debug features. | All | +| | This switch is used for accurate power and current measurements. | | ++-------------------+-------------------------------------------------------------------------------------+---------------------------------------+ + +.. _nrf53_audio_app_ui_buttons: + +Buttons +******* + +The application uses the following buttons on the supported development kit: + ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| Button | Function | Applications | ++===============+===========================================================================================================+=============================================+ +| **VOL-** | Long-pressed during startup: Changes the headset to the left channel one. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed on the headset or the CIS gateway during playback: Turns the playback volume down. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **VOL+** | Long-pressed during startup: Changes the headset to the right channel one. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed on the headset or the CIS gateway during playback: Turns the playback volume up. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **PLAY/PAUSE**| Starts or pauses the playback of the stream or listening to the stream. | All | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **BTN 4** | Long-pressed during startup: Turns on the DFU mode, if | All | +| | the device is :ref:`configured for it`. | | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed on the gateway during playback: Toggles between the normal audio stream and different test | * :ref:`nrf53_audio_broadcast_source_app` | +| | tones generated on the device. Use this tone to check the synchronization of headsets. | * :ref:`nrf53_audio_unicast_client_app` | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Pressed on the gateway during playback multiple times: Changes the test tone frequency. | | +| | The available values are 1000 Hz, 2000 Hz, and 4000 Hz. | | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed on a BIS headset during playback: Change stream (different BIS), if more than one is available. | :ref:`nrf53_audio_broadcast_sink_app` | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **BTN 5** | Long-pressed during startup: Clears the previously stored bonding information. | * :ref:`nrf53_audio_unicast_server_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed during playback: Mutes the playback volume. | * :ref:`nrf53_audio_unicast_server_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Pressed on a BIS headset during playback: Change the gateway, if more than one is available. | :ref:`nrf53_audio_broadcast_sink_app` | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **RESET** | Resets the device to the originally programmed settings. | All | +| | This reverts any changes made during testing, for example the channel switches with **VOL** buttons. | | ++---------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ + +.. _nrf53_audio_app_ui_leds: + +LEDs +**** + +To indicate the tasks performed, the application uses the LED behavior described in the following table: + ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| LED |Indication | Applications | ++==========================+===========================================================================================================+=============================================+ +| **LED1** | Off - No Bluetooth connection. | All | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid blue on the CIS gateway and headset: Kits have connected. | * :ref:`nrf53_audio_unicast_server_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid blue on the BIS headset: Kits have found a broadcasting stream. | :ref:`nrf53_audio_broadcast_sink_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Blinking blue on headset: Kits have started streaming audio (BIS and CIS modes). | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Blinking blue on the CIS gateway: Kit is streaming to a headset. | :ref:`nrf53_audio_unicast_client_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Blinking blue on the BIS gateway: Kit has started broadcasting audio. | :ref:`nrf53_audio_broadcast_source_app` | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **LED2** | Off - Sync not achieved. | All | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid green - Sync achieved (both drift and presentation compensation are in the ``LOCKED`` state). | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **LED3** | Blinking green - The nRF5340 Audio DK application core is running. | All | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **CODEC** | Off - No configuration loaded to the onboard hardware codec. | All | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid green - Hardware codec configuration loaded. | All | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **RGB** | Solid green - The device is programmed as the gateway. | * :ref:`nrf53_audio_broadcast_source_app` | +| | | * :ref:`nrf53_audio_unicast_client_app` | +| (bottom side LEDs around +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| the center opening) | Solid blue - The device is programmed as the left headset. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid magenta - The device is programmed as the right headset. | * :ref:`nrf53_audio_broadcast_sink_app` | +| | | * :ref:`nrf53_audio_unicast_server_app` | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid yellow - The device is programmed with factory firmware. | All | +| | It must be re-programmed as gateway or headset. | | +| +-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| | Solid red (debug mode) - Fault in the application core has occurred. | All | +| | See UART log for details and use the **RESET** button to reset the device. | | +| | In the release mode, the device resets automatically with no indication on LED or UART. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **ERR** | PMIC error or a charging error (or both). | All | +| | Also turns on when charging the battery exceeds seven hours, since the PMIC has a protection timeout, | | +| | which stops the charging. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **CHG** | Off - Charge completed or no battery connected. | All | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Solid yellow - Charging in progress. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **OB/EXT** | Off - No 3.3 V power available. | All | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Solid green - On-board hardware codec selected. | | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Solid yellow - External hardware codec selected. | | +| | This LED turns solid yellow also when the devices are reset, for the time then pins are floating. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **FTDI SPI** | Off - No data is written to the hardware codec using SPI. | All | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Yellow - The same SPI is used for both the hardware codec and the SD card. | | +| | When this LED is yellow, the shared SPI is used by the FTDI to write data to the hardware codec. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **IFMCU** | Off - No PC connection available. | All | +| (bottom side) +-----------------------------------------------------------------------------------------------------------+ | +| | Solid green - Connected to PC. | | +| +-----------------------------------------------------------------------------------------------------------+ | +| | Rapid green flash - USB enumeration failed. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ +| **HUB** | Off - No PC connection available. | All | +| (bottom side) +-----------------------------------------------------------------------------------------------------------+ | +| | Green - Standard USB hub operation. | | ++--------------------------+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+ diff --git a/applications/nrf5340_audio/include/nrf5340_audio_common.h b/applications/nrf5340_audio/include/nrf5340_audio_common.h index e4c06bd8ef5..d30c8b39eb2 100644 --- a/applications/nrf5340_audio/include/nrf5340_audio_common.h +++ b/applications/nrf5340_audio/include/nrf5340_audio_common.h @@ -7,6 +7,8 @@ #ifndef _NRF5340_AUDIO_COMMON_H_ #define _NRF5340_AUDIO_COMMON_H_ +#include + #define ZBUS_READ_TIMEOUT_MS K_MSEC(100) #define ZBUS_ADD_OBS_TIMEOUT_MS K_MSEC(200) @@ -34,10 +36,16 @@ struct le_audio_msg { enum le_audio_evt_type event; struct bt_conn *conn; struct bt_le_per_adv_sync *pa_sync; + enum bt_audio_dir dir; }; +/** + * tx_sync_ts_us The timestamp from get_tx_sync. + * curr_ts_us The current time. This must be in the controller frame of reference. + */ struct sdu_ref_msg { - uint32_t timestamp; + uint32_t tx_sync_ts_us; + uint32_t curr_ts_us; bool adjust; }; @@ -81,4 +89,11 @@ struct content_control_msg { enum content_control_evt_type event; }; +/** + * @brief Initialize the software modules that are common for all the audio samples. + * + * @return 0 if successful, error otherwise. + */ +int nrf5340_audio_common_init(void); + #endif /* _NRF5340_AUDIO_COMMON_H_ */ diff --git a/applications/nrf5340_audio/index.rst b/applications/nrf5340_audio/index.rst new file mode 100644 index 00000000000..a1221002fe8 --- /dev/null +++ b/applications/nrf5340_audio/index.rst @@ -0,0 +1,56 @@ +.. _nrf53_audio_app: + +nRF5340 Audio applications +########################## + +The nRF5340 Audio applications demonstrate audio playback over isochronous channels (ISO) using LC3 codec compression and decompression, as per `Bluetooth® LE Audio specifications`_. + +.. note:: + nRF5340 Audio applications and their DFU/FOTA functionality are marked as :ref:`experimental `. + +The following table summarizes the differences between the available nRF5340 Audio applications. + +.. list-table:: Differences between nRF5340 Audio applications + :header-rows: 1 + + * - :ref:`Application name (LE Audio role) ` + - :ref:`Application mode ` + - Minimum amount of nRF5340 Audio DKs recommended for testing + - :ref:`FEM support ` + * - :ref:`Broadcast sink` + - BIS (headset) + - 2 + - + * - :ref:`Broadcast source` + - BIS (gateway) + - 2 + - ✔ + * - :ref:`Unicast client` + - CIS (gateway) + - 3 + - ✔ + * - :ref:`Unicast server` + - CIS (headset) + - 3 + - ✔ + +See the subpages for detailed documentation of each of the nRF5340 applications and their internal modules: + +.. _nrf53_audio_app_subpages: + +.. toctree:: + :maxdepth: 1 + :caption: Subpages: + + doc/firmware_architecture + doc/feature_support + doc/requirements + doc/user_interface + doc/configuration + doc/building + broadcast_sink/README + broadcast_source/README + unicast_client/README + unicast_server/README + doc/fota + doc/adapting_application diff --git a/applications/nrf5340_audio/prj.conf b/applications/nrf5340_audio/prj.conf index 938193cc1ba..65b79447d10 100644 --- a/applications/nrf5340_audio/prj.conf +++ b/applications/nrf5340_audio/prj.conf @@ -7,6 +7,9 @@ # nRF5340 Audio CONFIG_NRF5340_AUDIO=y +CONFIG_SAMPLE_RATE_CONVERTER=y +CONFIG_SAMPLE_RATE_CONVERTER_FILTER_SIMPLE=y + # General CONFIG_DEBUG=y CONFIG_DEBUG_INFO=y @@ -25,6 +28,10 @@ CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y CONFIG_LOG_TAG_MAX_LEN=2 CONFIG_LOG_TAG_DEFAULT="--" CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_BUFFER_SIZE=4096 + +# Use this for debugging thread usage +#CONFIG_LOG_THREAD_ID_PREFIX=y # Console related defines CONFIG_CONSOLE=y @@ -39,6 +46,7 @@ CONFIG_USE_SEGGER_RTT=y CONFIG_SHELL_RTT_INIT_LOG_LEVEL_NONE=y CONFIG_SHELL_BACKEND_RTT=y CONFIG_SHELL_BACKEND_SERIAL=n +CONFIG_SHELL_VT100_COMMANDS=y CONFIG_SHELL_VT100_COLORS=y CONFIG_SHELL_STACK_SIZE=4096 CONFIG_SHELL_CMD_BUFF_SIZE=128 diff --git a/applications/nrf5340_audio/prj_release.conf b/applications/nrf5340_audio/prj_release.conf index 0b669855c6c..1adec71c029 100644 --- a/applications/nrf5340_audio/prj_release.conf +++ b/applications/nrf5340_audio/prj_release.conf @@ -7,6 +7,9 @@ # nRF5340 Audio CONFIG_NRF5340_AUDIO=y +CONFIG_SAMPLE_RATE_CONVERTER=y +CONFIG_SAMPLE_RATE_CONVERTER_FILTER_SIMPLE=y + # General CONFIG_DEBUG=n CONFIG_ASSERT=n diff --git a/applications/nrf5340_audio/sample.yaml b/applications/nrf5340_audio/sample.yaml index 1bc3545dc15..2150b28376a 100644 --- a/applications/nrf5340_audio/sample.yaml +++ b/applications/nrf5340_audio/sample.yaml @@ -17,30 +17,6 @@ tests: platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns tags: ci_build extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=2 - applications.nrf5340_audio.hs_d_i: - build_only: true - platform_allow: nrf5340_audio_dk_nrf5340_cpuapp - platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns - tags: ci_build - extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=1 CONFIG_AUDIO_DFU=1 - applications.nrf5340_audio.gw_d_i: - build_only: true - platform_allow: nrf5340_audio_dk_nrf5340_cpuapp - platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns - tags: ci_build - extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=2 CONFIG_AUDIO_DFU=1 - applications.nrf5340_audio.hs_d_e: - build_only: true - platform_allow: nrf5340_audio_dk_nrf5340_cpuapp - platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns - tags: ci_build - extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=1 CONFIG_AUDIO_DFU=2 - applications.nrf5340_audio.gw_d_e: - build_only: true - platform_allow: nrf5340_audio_dk_nrf5340_cpuapp - platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns - tags: ci_build - extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=2 CONFIG_AUDIO_DFU=2 applications.nrf5340_audio.headset_sd_card_playback: build_only: true platform_allow: nrf5340_audio_dk_nrf5340_cpuapp diff --git a/applications/nrf5340_audio/src/audio/CMakeLists.txt b/applications/nrf5340_audio/src/audio/CMakeLists.txt index 935b301abd2..306830c807d 100644 --- a/applications/nrf5340_audio/src/audio/CMakeLists.txt +++ b/applications/nrf5340_audio/src/audio/CMakeLists.txt @@ -10,23 +10,3 @@ target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/sw_codec_select.c ${CMAKE_CURRENT_SOURCE_DIR}/le_audio_rx.c ) - -if (CONFIG_BT_BAP_BROADCAST_SINK) - target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/streamctrl_broadcast_sink.c) -endif() - -if (CONFIG_BT_BAP_BROADCAST_SOURCE) - target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/streamctrl_broadcast_source.c) -endif() - -if (CONFIG_BT_BAP_UNICAST_CLIENT) - target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/streamctrl_unicast_client.c) -endif() - -if (CONFIG_BT_BAP_UNICAST_SERVER) - target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/streamctrl_unicast_server.c) -endif() diff --git a/applications/nrf5340_audio/src/audio/Kconfig b/applications/nrf5340_audio/src/audio/Kconfig index 512f0024484..8d966509133 100644 --- a/applications/nrf5340_audio/src/audio/Kconfig +++ b/applications/nrf5340_audio/src/audio/Kconfig @@ -43,13 +43,18 @@ config AUDIO_MAX_PRES_DLY_US help The maximum presentation delay in micro seconds. -choice AUDIO_SAMPLE_RATE - prompt "Audio sample rate" - default AUDIO_SAMPLE_RATE_16000_HZ if BT_BAP_BROADCAST_16_2_1 || BT_BAP_BROADCAST_16_2_2 || BT_BAP_UNICAST_16_2_1 - default AUDIO_SAMPLE_RATE_24000_HZ if BT_BAP_BROADCAST_24_2_1 || BT_BAP_BROADCAST_24_2_2 || BT_BAP_UNICAST_24_2_1 +choice AUDIO_SYSTEM_SAMPLE_RATE + prompt "System audio sample rate" + default AUDIO_SAMPLE_RATE_16000_HZ if BT_BAP_BROADCAST_16_2_1 + default AUDIO_SAMPLE_RATE_16000_HZ if BT_BAP_BROADCAST_16_2_2 + default AUDIO_SAMPLE_RATE_16000_HZ if BT_BAP_UNICAST_16_2_1 + default AUDIO_SAMPLE_RATE_24000_HZ if BT_BAP_BROADCAST_24_2_1 + default AUDIO_SAMPLE_RATE_24000_HZ if BT_BAP_BROADCAST_24_2_2 + default AUDIO_SAMPLE_RATE_24000_HZ if BT_BAP_UNICAST_24_2_1 default AUDIO_SAMPLE_RATE_48000_HZ help - This will be selected based on the BAP settings. + This configuration reflects the system sample rate, but the audio data may be resampled to + another sample rate before encoding, and after decoding. config AUDIO_SAMPLE_RATE_16000_HZ bool "16 kHz" @@ -157,6 +162,7 @@ endchoice config AUDIO_TEST_TONE bool "Test tone instead of doing user defined action" + select TONE default y help Use button 4 to set a test tone @@ -342,13 +348,13 @@ menu "Stack sizes" config ENCODER_STACK_SIZE int "Stack size for encoder thread" - default 7500 if AUDIO_BIT_DEPTH_16 - default 11264 if AUDIO_BIT_DEPTH_32 + default 11000 if AUDIO_BIT_DEPTH_16 + default 21400 if AUDIO_BIT_DEPTH_32 config AUDIO_DATAPATH_STACK_SIZE int "Stack size for audio datapath thread" - default 4096 if AUDIO_BIT_DEPTH_16 - default 8192 if AUDIO_BIT_DEPTH_32 + default 7600 if AUDIO_BIT_DEPTH_16 + default 14700 if AUDIO_BIT_DEPTH_32 config BUTTON_MSG_SUB_STACK_SIZE int "Stack size for button subscriber" diff --git a/applications/nrf5340_audio/src/audio/Kconfig.defaults b/applications/nrf5340_audio/src/audio/Kconfig.defaults index 58a6c6a68a0..809aad94e4d 100644 --- a/applications/nrf5340_audio/src/audio/Kconfig.defaults +++ b/applications/nrf5340_audio/src/audio/Kconfig.defaults @@ -11,60 +11,3 @@ config NRFX_TIMER1 # Audio sync timer config NRFX_DPPI default y - -# Required for calculating test tones -config CMSIS_DSP - default y - -# HEADSET -if AUDIO_DEV = 1 - -if TRANSPORT_CIS # Depends on TRANSPORT_CIS - -config LC3_BITRATE - default BT_AUDIO_BITRATE_UNICAST_SRC - -endif # TRANSPORT_CIS - -config LC3_ENC_CHAN_MAX - default 1 - -config LC3_DEC_CHAN_MAX - default 1 - -if TRANSPORT_BIS # Depends on TRANSPORT_BIS - -config AUDIO_TEST_TONE - default n - -config AUDIO_MUTE - default n - -endif # TRANSPORT_BIS - -endif # AUDIO_DEV = 1 (HEADSET) - -# GATEWAY -if AUDIO_DEV = 2 - -if TRANSPORT_CIS # Depends on TRANSPORT_CIS - -config LC3_BITRATE - default BT_AUDIO_BITRATE_UNICAST_SINK - -endif # TRANSPORT_CIS - -if TRANSPORT_BIS # Depends on TRANSPORT_BIS - -config LC3_BITRATE - default BT_AUDIO_BITRATE_BROADCAST_SRC - -endif # TRANSPORT_BIS - -config LC3_ENC_CHAN_MAX - default 2 - -config LC3_DEC_CHAN_MAX - default 1 - -endif # AUDIO_DEV = 2 (GATEWAY) diff --git a/applications/nrf5340_audio/src/audio/audio_datapath.c b/applications/nrf5340_audio/src/audio/audio_datapath.c index e4c1f0c9157..afe14b9fed6 100644 --- a/applications/nrf5340_audio/src/audio/audio_datapath.c +++ b/applications/nrf5340_audio/src/audio/audio_datapath.c @@ -48,13 +48,15 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL); #define MAX_FIFO_SIZE (FIFO_NUM_BLKS * BLK_SIZE_SAMPLES(CONFIG_AUDIO_SAMPLE_RATE_HZ) * 2) /* Number of audio blocks given a duration */ -#define NUM_BLKS(d) ((d) / BLK_PERIOD_US) +#define NUM_BLKS(d) ((d) / BLK_PERIOD_US) /* Single audio block size in number of samples (stereo) */ -#define BLK_SIZE_SAMPLES(r) (((r) * BLK_PERIOD_US) / 1000000) +/* clang-format off */ +#define BLK_SIZE_SAMPLES(r) (((r)*BLK_PERIOD_US) / 1000000) +/* clang-format on */ /* Increment sample FIFO index by one block */ -#define NEXT_IDX(i) (((i) < (FIFO_NUM_BLKS - 1)) ? ((i) + 1) : 0) +#define NEXT_IDX(i) (((i) < (FIFO_NUM_BLKS - 1)) ? ((i) + 1) : 0) /* Decrement sample FIFO index by one block */ -#define PREV_IDX(i) (((i) > 0) ? ((i)-1) : (FIFO_NUM_BLKS - 1)) +#define PREV_IDX(i) (((i) > 0) ? ((i)-1) : (FIFO_NUM_BLKS - 1)) #define NUM_BLKS_IN_FRAME NUM_BLKS(CONFIG_AUDIO_FRAME_DURATION_US) #define BLK_MONO_NUM_SAMPS BLK_SIZE_SAMPLES(CONFIG_AUDIO_SAMPLE_RATE_HZ) @@ -72,7 +74,9 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL); #define APLL_FREQ_MIN 36834 #define APLL_FREQ_MAX 42874 /* Use nanoseconds to reduce rounding errors */ -#define APLL_FREQ_ADJ(t) (-((t) * 1000) / 331) +/* clang-format off */ +#define APLL_FREQ_ADJ(t) (-((t)*1000) / 331) +/* clang-format on */ #define DRIFT_MEAS_PERIOD_US 100000 #define DRIFT_ERR_THRESH_LOCK 16 @@ -80,11 +84,11 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL); /* To get smaller corrections */ #define DRIFT_REGULATOR_DIV_FACTOR 2 -/* 4000 us to allow BLE transmission and (host -> HCI -> controller) */ -#define JUST_IN_TIME_US (CONFIG_AUDIO_FRAME_DURATION_US - 4000) -#define JUST_IN_TIME_THRESHOLD_US 2000 +/* To allow BLE transmission and (host -> HCI -> controller) */ +#define JUST_IN_TIME_TARGET_DLY_US 3000 +#define JUST_IN_TIME_BOUND_US 2500 -/* How often to print underrun warning */ +/* How often to print under-run warning */ #define UNDERRUN_LOG_INTERVAL_BLKS 5000 enum drift_comp_state { @@ -137,7 +141,8 @@ static struct { uint32_t total_blk_underruns; } out; - uint32_t previous_sdu_ref_us; + uint32_t prev_drift_sdu_ref_us; + uint32_t prev_pres_sdu_ref_us; uint32_t current_pres_dly_us; struct { @@ -163,30 +168,20 @@ static uint16_t test_tone_buf[CONFIG_AUDIO_SAMPLE_RATE_HZ / 100]; static size_t test_tone_size; /** - * @brief Calculate error between sdu_ref and frame_start_ts. + * @brief Calculate error between sdu_ref and frame_start_ts_us. * * @note Used to adjust audio clock to account for drift. * * @param sdu_ref_us Timestamp for SDU. - * @param frame_start_ts Timestamp for I2S. + * @param frame_start_ts_us Timestamp for I2S. * * @return Error in microseconds (err_us). */ -static int32_t err_us_calculate(uint32_t sdu_ref_us, uint32_t frame_start_ts) +static int32_t err_us_calculate(uint32_t sdu_ref_us, uint32_t frame_start_ts_us) { bool err_neg = false; - if (IS_ENABLED(CONFIG_BT_LL_ACS_NRF53) && IS_ENABLED(CONFIG_TRANSPORT_BIS)) { - /* To make the drift compensation work as expected - * when using the LE Audio Controller Subsystem Link Layer - * and BIS we must add CONFIG_AUDIO_FRAME_DURATION_US to - * sdu_ref_us. - * This is a temporary workaround. - */ - sdu_ref_us += CONFIG_AUDIO_FRAME_DURATION_US; - } - - int64_t total_err = ((int64_t)sdu_ref_us - (int64_t)frame_start_ts); + int64_t total_err = ((int64_t)sdu_ref_us - (int64_t)frame_start_ts_us); /* Store sign for later use, since remainder operation is undefined for negatives */ if (total_err < 0) { @@ -231,19 +226,25 @@ static void drift_comp_state_set(enum drift_comp_state new_state) } /** - * @brief Adjust frequency of HFCLKAUDIO to get audio in sync + * @brief Adjust frequency of HFCLKAUDIO to get audio in sync. * - * @note The audio sync is based on sdu_ref_us + * @note The audio sync is based on sdu_ref_us. * - * @param frame_start_ts I2S frame start timestamp + * @param frame_start_ts_us I2S frame start timestamp. */ -static void audio_datapath_drift_compensation(uint32_t frame_start_ts) +static void audio_datapath_drift_compensation(uint32_t frame_start_ts_us) { + if (CONFIG_AUDIO_DEV == HEADSET) { + /** For headsets we do not use the timestamp gotten from hci_tx_sync_get to adjust + * for drift + */ + ctrl_blk.prev_drift_sdu_ref_us = ctrl_blk.prev_pres_sdu_ref_us; + } switch (ctrl_blk.drift_comp.state) { case DRIFT_STATE_INIT: { /* Check if audio data has been received */ - if (ctrl_blk.previous_sdu_ref_us) { - ctrl_blk.drift_comp.meas_start_time_us = ctrl_blk.previous_sdu_ref_us; + if (ctrl_blk.prev_drift_sdu_ref_us) { + ctrl_blk.drift_comp.meas_start_time_us = ctrl_blk.prev_drift_sdu_ref_us; drift_comp_state_set(DRIFT_STATE_CALIB); } @@ -258,7 +259,7 @@ static void audio_datapath_drift_compensation(uint32_t frame_start_ts) ctrl_blk.drift_comp.ctr = 0; - int32_t err_us = DRIFT_MEAS_PERIOD_US - (ctrl_blk.previous_sdu_ref_us - + int32_t err_us = DRIFT_MEAS_PERIOD_US - (ctrl_blk.prev_drift_sdu_ref_us - ctrl_blk.drift_comp.meas_start_time_us); int32_t freq_adj = APLL_FREQ_ADJ(err_us); @@ -286,7 +287,8 @@ static void audio_datapath_drift_compensation(uint32_t frame_start_ts) ctrl_blk.drift_comp.ctr = 0; - int32_t err_us = err_us_calculate(ctrl_blk.previous_sdu_ref_us, frame_start_ts); + int32_t err_us = + err_us_calculate(ctrl_blk.prev_drift_sdu_ref_us, frame_start_ts_us); err_us /= DRIFT_REGULATOR_DIV_FACTOR; int32_t freq_adj = APLL_FREQ_ADJ(err_us); @@ -307,7 +309,8 @@ static void audio_datapath_drift_compensation(uint32_t frame_start_ts) ctrl_blk.drift_comp.ctr = 0; - int32_t err_us = err_us_calculate(ctrl_blk.previous_sdu_ref_us, frame_start_ts); + int32_t err_us = + err_us_calculate(ctrl_blk.prev_drift_sdu_ref_us, frame_start_ts_us); err_us /= DRIFT_REGULATOR_DIV_FACTOR; int32_t freq_adj = APLL_FREQ_ADJ(err_us); @@ -346,14 +349,14 @@ static void pres_comp_state_set(enum pres_comp_state new_state) } /** - * @brief Move audio blocks back and forth in FIFO to get audio in sync. + * @brief Move audio blocks back and forth in FIFO to get audio in sync. * - * @note The audio sync is based on sdu_ref_us. + * @note The audio sync is based on sdu_ref_us. * - * @param recv_frame_ts_us Timestamp of when frame was received. - * @param sdu_ref_us ISO timestamp reference from Bluetooth LE controller. - * @param sdu_ref_not_consecutive True if sdu_ref_us and the previous sdu_ref_us - * originate from non-consecutive frames. + * @param recv_frame_ts_us Timestamp of when frame was received. + * @param sdu_ref_us ISO timestamp reference from Bluetooth LE controller. + * @param sdu_ref_not_consecutive True if sdu_ref_us and the previous sdu_ref_us + * originate from non-consecutive frames. */ static void audio_datapath_presentation_compensation(uint32_t recv_frame_ts_us, uint32_t sdu_ref_us, bool sdu_ref_not_consecutive) @@ -501,10 +504,15 @@ int audio_datapath_tone_play(uint16_t freq, uint16_t dur_ms, float amplitude) return -EBUSY; } - ret = tone_gen(test_tone_buf, &test_tone_size, freq, CONFIG_AUDIO_SAMPLE_RATE_HZ, - amplitude); - if (ret) { - return ret; + if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { + ret = tone_gen(test_tone_buf, &test_tone_size, freq, CONFIG_AUDIO_SAMPLE_RATE_HZ, + amplitude); + if (ret) { + return ret; + } + } else { + LOG_ERR("Test tone is not enabled"); + return -ENXIO; } /* If duration is 0, play forever */ @@ -539,7 +547,7 @@ static void tone_mix(uint8_t *tx_buf) } /* Alternate-buffers used when there is no active audio stream. - * Used interchangably by I2S. + * Used interchangeably by I2S. */ static struct { uint8_t __aligned(WB_UP(1)) buf_0[BLK_STEREO_SIZE_OCTETS]; @@ -549,12 +557,12 @@ static struct { } alt; /** - * @brief Get first available alternative-buffer + * @brief Get first available alternative-buffer. * - * @param p_buffer Double pointer to populate with buffer + * @param p_buffer Double pointer to populate with buffer. * - * @retval 0 if success - * @retval -ENOMEM No available buffers + * @retval 0 if success. + * @retval -ENOMEM No available buffers. */ static int alt_buffer_get(void **p_buffer) { @@ -572,10 +580,10 @@ static int alt_buffer_get(void **p_buffer) } /** - * @brief Checks if pointer matches that of a buffer - * and frees it in one operation + * @brief Checks if pointer matches that of a buffer + * and frees it in one operation. * - * @param p_buffer Buffer to free + * @param p_buffer Buffer to free. */ static void alt_buffer_free(void const *const p_buffer) { @@ -587,7 +595,7 @@ static void alt_buffer_free(void const *const p_buffer) } /** - * @brief Frees both alternative buffers + * @brief Frees both alternative buffers. */ static void alt_buffer_free_both(void) { @@ -605,7 +613,7 @@ static void alt_buffer_free_both(void) * New I2S RX data is located in rx_buf_released, and is locked into * the in.fifo message queue. */ -static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts, uint32_t *rx_buf_released, +static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts_us, uint32_t *rx_buf_released, uint32_t const *tx_buf_released) { int ret; @@ -615,7 +623,7 @@ static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts, uint32_t *r /*** Presentation delay measurement ***/ ctrl_blk.current_pres_dly_us = - frame_start_ts - ctrl_blk.out.prod_blk_ts[ctrl_blk.out.cons_blk_idx]; + frame_start_ts_us - ctrl_blk.out.prod_blk_ts[ctrl_blk.out.cons_blk_idx]; /********** I2S TX **********/ static uint8_t *tx_buf; @@ -626,11 +634,11 @@ static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts, uint32_t *r uint32_t next_out_blk_idx = NEXT_IDX(ctrl_blk.out.cons_blk_idx); if (next_out_blk_idx != ctrl_blk.out.prod_blk_idx) { - /* Only increment if not in underrun condition */ + /* Only increment if not in under-run condition */ ctrl_blk.out.cons_blk_idx = next_out_blk_idx; if (underrun_condition) { underrun_condition = false; - LOG_WRN("Data received, total underruns: %d", + LOG_WRN("Data received, total under-runs: %d", ctrl_blk.out.total_blk_underruns); } @@ -644,7 +652,7 @@ static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts, uint32_t *r if ((ctrl_blk.out.total_blk_underruns % UNDERRUN_LOG_INTERVAL_BLKS) == 0) { - LOG_WRN("In I2S TX underrun condition, total: %d", + LOG_WRN("In I2S TX under-run condition, total: %d", ctrl_blk.out.total_blk_underruns); } } @@ -714,7 +722,7 @@ static void audio_datapath_i2s_blk_complete(uint32_t frame_start_ts, uint32_t *r /*** Drift compensation ***/ if (ctrl_blk.drift_comp.enabled) { - audio_datapath_drift_compensation(frame_start_ts); + audio_datapath_drift_compensation(frame_start_ts_us); } } @@ -746,7 +754,7 @@ static void audio_datapath_i2s_start(void) ret = data_fifo_num_used_get(ctrl_blk.in.fifo, &alloced_cnt, &locked_cnt); if (alloced_cnt || locked_cnt || ret) { - ERR_CHK_MSG(-ENOMEM, "Fifo is not empty!"); + ERR_CHK_MSG(-ENOMEM, "FIFO is not empty!"); } ret = data_fifo_pointer_first_vacant_get(ctrl_blk.in.fifo, (void **)&rx_buf_one, @@ -769,69 +777,87 @@ static void audio_datapath_i2s_stop(void) } /** - * @brief Adjust timing to make sure audio data is sent just in time for Bluetooth LE event. + * @brief Adjust timing to make sure audio data is sent just in time for Bluetooth LE event. * - * @note The time from last anchor point is checked and then blocks of 1ms - * can be dropped to allow the sending of encoded data to be sent just - * before the connection interval opens up. This is done to reduce overall - * latency. + * @note The time from last anchor point is checked and then blocks of 1 ms can be dropped + * to allow the sending of encoded data to be sent just before the connection interval + * opens up. This is done to reduce overall latency. * - * @param[in] sdu_ref_us The SDU reference, in µs, to the previous sent packet + * @param[in] tx_sync_ts_us The timestamp from get_tx_sync. + * @param[in] curr_ts_us The current time. This must be in the controller frame of reference. */ -static void audio_datapath_just_in_time_check_and_adjust(uint32_t sdu_ref_us) +static void audio_datapath_just_in_time_check_and_adjust(uint32_t tx_sync_ts_us, + uint32_t curr_ts_us) { - static int32_t count; int ret; + static int32_t print_count; + int64_t diff; - uint32_t curr_frame_ts = audio_sync_timer_capture(); - int diff = curr_frame_ts - sdu_ref_us; + diff = (int64_t)tx_sync_ts_us - curr_ts_us; - if (count++ % 100 == 0) { - LOG_DBG("Time from last anchor: %d", diff); + /* + * The diff should always be positive. If diff is a large negative number, it is likely + * that wrapping has occurred. A small negative value however, may point to the application + * sending data too late, and we need to drop data to get back in sync with the controller. + */ + if (diff < -((int64_t)UINT32_MAX / 2)) { + LOG_DBG("Timestamp wrap. diff: %lld", diff); + diff += UINT32_MAX; + + } else if (diff < 0) { + LOG_DBG("tx_sync_ts_us: %u is earlier than curr_ts_us %u", tx_sync_ts_us, + curr_ts_us); } - if ((diff < (JUST_IN_TIME_US - JUST_IN_TIME_THRESHOLD_US)) || - (diff > (JUST_IN_TIME_US + JUST_IN_TIME_THRESHOLD_US))) { + if (print_count % 100 == 0) { + LOG_DBG("JIT diff: %lld us. Target: %u +/- %u", diff, JUST_IN_TIME_TARGET_DLY_US, + JUST_IN_TIME_BOUND_US); + } + print_count++; + + if ((diff < (JUST_IN_TIME_TARGET_DLY_US - JUST_IN_TIME_BOUND_US)) || + (diff > (JUST_IN_TIME_TARGET_DLY_US + JUST_IN_TIME_BOUND_US))) { ret = audio_system_fifo_rx_block_drop(); if (ret) { LOG_WRN("Not able to drop FIFO RX block"); return; } - - count = 0; + LOG_DBG("Dropped block to align with connection interval"); + print_count = 0; } } /** - * @brief Update sdu_ref_us so that drift compensation can work correctly. + * @brief Update sdu_ref_us so that drift compensation can work correctly. * - * @note This function is only valid for gateway using I2S as audio source - * and unidirectional audio stream (gateway to one or more headsets). + * @note This function is only valid for gateway using I2S as audio source + * and unidirectional audio stream (gateway to one or more headsets). * - * @param sdu_ref_us ISO timestamp reference from Bluetooth LE controller. - * @param adjust Indicate if the sdu_ref should be used to adjust timing. + * @param sdu_ref_us ISO timestamp reference from Bluetooth LE controller. + * @param adjust Indicate if the sdu_ref should be used to adjust timing. */ static void audio_datapath_sdu_ref_update(const struct zbus_channel *chan) { if (IS_ENABLED(CONFIG_AUDIO_SOURCE_I2S)) { - uint32_t sdu_ref_us; + uint32_t tx_sync_ts_us; + uint32_t curr_ts_us; bool adjust; const struct sdu_ref_msg *msg; msg = zbus_chan_const_msg(chan); - sdu_ref_us = msg->timestamp; + tx_sync_ts_us = msg->tx_sync_ts_us; + curr_ts_us = msg->curr_ts_us; adjust = msg->adjust; if (ctrl_blk.stream_started) { - ctrl_blk.previous_sdu_ref_us = sdu_ref_us; + ctrl_blk.prev_drift_sdu_ref_us = tx_sync_ts_us; - if (adjust && sdu_ref_us != 0) { - if (IS_ENABLED(CONFIG_BT_LL_ACS_NRF53)) { - audio_datapath_just_in_time_check_and_adjust(sdu_ref_us); - } + if (adjust && tx_sync_ts_us != 0) { + audio_datapath_just_in_time_check_and_adjust(tx_sync_ts_us, + curr_ts_us); } } else { - LOG_WRN("Stream not startet - Can not update sdu_ref_us"); + LOG_WRN("Stream not started - Can not update tx_sync_ts_us"); } } } @@ -868,23 +894,18 @@ void audio_datapath_stream_out(const uint8_t *buf, size_t size, uint32_t sdu_ref /*** Check incoming data ***/ if (!buf) { - LOG_ERR("buf is NULL"); + LOG_ERR("Buffer pointer is NULL"); } - if (sdu_ref_us == ctrl_blk.previous_sdu_ref_us && sdu_ref_us != 0) { + if (sdu_ref_us == ctrl_blk.prev_pres_sdu_ref_us && sdu_ref_us != 0) { LOG_WRN("Duplicate sdu_ref_us (%d) - Dropping audio frame", sdu_ref_us); return; } - if (bad_frame) { - /* Error in the frame or frame lost - sdu_ref_us is stil valid */ - LOG_DBG("Bad audio frame"); - } - bool sdu_ref_not_consecutive = false; - if (ctrl_blk.previous_sdu_ref_us) { - uint32_t sdu_ref_delta_us = sdu_ref_us - ctrl_blk.previous_sdu_ref_us; + if (ctrl_blk.prev_pres_sdu_ref_us) { + uint32_t sdu_ref_delta_us = sdu_ref_us - ctrl_blk.prev_pres_sdu_ref_us; /* Check if the delta is from two consecutive frames */ if (sdu_ref_delta_us < @@ -898,7 +919,7 @@ void audio_datapath_stream_out(const uint8_t *buf, size_t size, uint32_t sdu_ref sdu_ref_delta_us); /* Estimate sdu_ref_us */ - sdu_ref_us = ctrl_blk.previous_sdu_ref_us + + sdu_ref_us = ctrl_blk.prev_pres_sdu_ref_us + CONFIG_AUDIO_FRAME_DURATION_US; } } else { @@ -908,7 +929,7 @@ void audio_datapath_stream_out(const uint8_t *buf, size_t size, uint32_t sdu_ref } } - ctrl_blk.previous_sdu_ref_us = sdu_ref_us; + ctrl_blk.prev_pres_sdu_ref_us = sdu_ref_us; /*** Presentation compensation ***/ if (ctrl_blk.pres_comp.enabled) { @@ -933,7 +954,8 @@ void audio_datapath_stream_out(const uint8_t *buf, size_t size, uint32_t sdu_ref } if (pcm_size != (BLK_STEREO_SIZE_OCTETS * NUM_BLKS_IN_FRAME)) { - LOG_WRN("Decoded audio has wrong size"); + LOG_WRN("Decoded audio has wrong size: %d. Expected: %d", pcm_size, + (BLK_STEREO_SIZE_OCTETS * NUM_BLKS_IN_FRAME)); /* Discard frame */ return; } @@ -1000,7 +1022,8 @@ int audio_datapath_stop(void) if (ctrl_blk.stream_started) { ctrl_blk.stream_started = false; audio_datapath_i2s_stop(); - ctrl_blk.previous_sdu_ref_us = 0; + ctrl_blk.prev_pres_sdu_ref_us = 0; + ctrl_blk.prev_drift_sdu_ref_us = 0; pres_comp_state_set(PRES_STATE_INIT); @@ -1018,6 +1041,7 @@ int audio_datapath_init(void) ctrl_blk.datapath_initialized = true; ctrl_blk.drift_comp.enabled = true; ctrl_blk.pres_comp.enabled = true; + ctrl_blk.pres_comp.pres_delay_us = CONFIG_BT_AUDIO_PRESENTATION_DELAY_US; return 0; @@ -1070,7 +1094,7 @@ static int cmd_i2s_tone_play(const struct shell *shell, size_t argc, const char } shell_print(shell, "Tone play: %d Hz for %d ms with amplitude %.02f", freq, dur_ms, - amplitude); + (double)amplitude); return ret; } diff --git a/applications/nrf5340_audio/src/audio/audio_system.c b/applications/nrf5340_audio/src/audio/audio_system.c index e34c399a714..7174030241f 100644 --- a/applications/nrf5340_audio/src/audio/audio_system.c +++ b/applications/nrf5340_audio/src/audio/audio_system.c @@ -35,14 +35,30 @@ K_THREAD_STACK_DEFINE(encoder_thread_stack, CONFIG_ENCODER_STACK_SIZE); DATA_FIFO_DEFINE(fifo_tx, FIFO_TX_BLOCK_COUNT, WB_UP(BLOCK_SIZE_BYTES)); DATA_FIFO_DEFINE(fifo_rx, FIFO_RX_BLOCK_COUNT, WB_UP(BLOCK_SIZE_BYTES)); +static K_SEM_DEFINE(sem_encoder_start, 0, 1); + static struct k_thread encoder_thread_data; static k_tid_t encoder_thread_id; +static struct k_poll_signal encoder_sig; + +static struct k_poll_event encoder_evt = + K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &encoder_sig); + static struct sw_codec_config sw_codec_cfg; /* Buffer which can hold max 1 period test tone at 1000 Hz */ static int16_t test_tone_buf[CONFIG_AUDIO_SAMPLE_RATE_HZ / 1000]; static size_t test_tone_size; +static bool sample_rate_valid(uint32_t sample_rate_hz) +{ + if (sample_rate_hz == 16000 || sample_rate_hz == 24000 || sample_rate_hz == 48000) { + return true; + } + + return false; +} + static void audio_gateway_configure(void) { if (IS_ENABLED(CONFIG_SW_CODEC_LC3)) { @@ -52,17 +68,10 @@ static void audio_gateway_configure(void) } #if (CONFIG_STREAM_BIDIRECTIONAL) - sw_codec_cfg.decoder.enabled = true; sw_codec_cfg.decoder.num_ch = 1; sw_codec_cfg.decoder.channel_mode = SW_CODEC_MONO; #endif /* (CONFIG_STREAM_BIDIRECTIONAL) */ - if (IS_ENABLED(CONFIG_SW_CODEC_LC3)) { - sw_codec_cfg.encoder.bitrate = CONFIG_LC3_BITRATE; - } else { - ERR_CHK_MSG(-EINVAL, "No codec selected"); - } - if (IS_ENABLED(CONFIG_MONO_TO_ALL_RECEIVERS)) { sw_codec_cfg.encoder.num_ch = 1; } else { @@ -71,7 +80,6 @@ static void audio_gateway_configure(void) sw_codec_cfg.encoder.channel_mode = (sw_codec_cfg.encoder.num_ch == 1) ? SW_CODEC_MONO : SW_CODEC_STEREO; - sw_codec_cfg.encoder.enabled = true; } static void audio_headset_configure(void) @@ -83,15 +91,8 @@ static void audio_headset_configure(void) } #if (CONFIG_STREAM_BIDIRECTIONAL) - sw_codec_cfg.encoder.enabled = true; sw_codec_cfg.encoder.num_ch = 1; sw_codec_cfg.encoder.channel_mode = SW_CODEC_MONO; - - if (IS_ENABLED(CONFIG_SW_CODEC_LC3)) { - sw_codec_cfg.encoder.bitrate = CONFIG_LC3_BITRATE; - } else { - ERR_CHK_MSG(-EINVAL, "No codec selected"); - } #endif /* (CONFIG_STREAM_BIDIRECTIONAL) */ sw_codec_cfg.decoder.num_ch = 1; @@ -101,8 +102,6 @@ static void audio_headset_configure(void) /* Need an extra decoder channel to decode data from SD card */ sw_codec_cfg.decoder.num_ch++; } - - sw_codec_cfg.decoder.enabled = true; } static void encoder_thread(void *arg1, void *arg2, void *arg3) @@ -122,6 +121,9 @@ static void encoder_thread(void *arg1, void *arg2, void *arg3) static uint32_t test_tone_finite_pos; while (1) { + /* Don't start encoding until the stream needing it has started */ + ret = k_poll(&encoder_evt, 1, K_FOREVER); + /* Get PCM data from I2S */ /* Since one audio frame is divided into a number of * blocks, we need to fetch the pointers to all of these @@ -180,6 +182,17 @@ static void encoder_thread(void *arg1, void *arg2, void *arg3) } } +void audio_system_encoder_start(void) +{ + LOG_DBG("Encoder started"); + k_poll_signal_raise(&encoder_sig, 0); +} + +void audio_system_encoder_stop(void) +{ + k_poll_signal_reset(&encoder_sig); +} + int audio_system_encode_test_tone_set(uint32_t freq) { int ret; @@ -189,8 +202,14 @@ int audio_system_encode_test_tone_set(uint32_t freq) return 0; } - ret = tone_gen(test_tone_buf, &test_tone_size, freq, CONFIG_AUDIO_SAMPLE_RATE_HZ, 1); - ERR_CHK(ret); + if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { + ret = tone_gen(test_tone_buf, &test_tone_size, freq, CONFIG_AUDIO_SAMPLE_RATE_HZ, + 1); + ERR_CHK(ret); + } else { + LOG_ERR("Test tone is not enabled"); + return -ENXIO; + } if (test_tone_size > sizeof(test_tone_buf)) { return -ENOMEM; @@ -232,6 +251,32 @@ int audio_system_encode_test_tone_step(void) return 0; } +int audio_system_config_set(uint32_t encoder_sample_rate_hz, uint32_t encoder_bitrate, + uint32_t decoder_sample_rate_hz) +{ + if (sample_rate_valid(encoder_sample_rate_hz)) { + sw_codec_cfg.encoder.sample_rate_hz = encoder_sample_rate_hz; + } else if (encoder_sample_rate_hz) { + LOG_ERR("%d is not a valid sample rate", encoder_sample_rate_hz); + return -EINVAL; + } + + if (sample_rate_valid(decoder_sample_rate_hz)) { + sw_codec_cfg.decoder.enabled = true; + sw_codec_cfg.decoder.sample_rate_hz = decoder_sample_rate_hz; + } else if (decoder_sample_rate_hz) { + LOG_ERR("%d is not a valid sample rate", decoder_sample_rate_hz); + return -EINVAL; + } + + if (encoder_bitrate) { + sw_codec_cfg.encoder.enabled = true; + sw_codec_cfg.encoder.bitrate = encoder_bitrate; + } + + return 0; +} + /* This function is only used on gateway using USB as audio source and bidirectional stream */ int audio_system_decode(void const *const encoded_data, size_t encoded_data_size, bool bad_frame) { @@ -442,6 +487,8 @@ int audio_system_init(void) return ret; } #endif + k_poll_signal_init(&encoder_sig); + return 0; } diff --git a/applications/nrf5340_audio/src/audio/audio_system.h b/applications/nrf5340_audio/src/audio/audio_system.h index d682e52967f..ba6bebf516e 100644 --- a/applications/nrf5340_audio/src/audio/audio_system.h +++ b/applications/nrf5340_audio/src/audio/audio_system.h @@ -11,70 +11,100 @@ #include #include +#define VALUE_NOT_SET 0 + +/** + * @brief Start the execution of the encoder thread. + */ +void audio_system_encoder_start(void); + +/** + * @brief Stop the encoder thread from executing. + * + * @note Using this allows the encode thread to always be enabled, + * but disables the execution when not needed, saving power. + */ +void audio_system_encoder_stop(void); + /** - * @brief Toggle a test tone on and off. + * @brief Toggle a test tone on and off. * - * @param[in] freq Desired frequency of tone. Off if set to 0. + * @note A stream must already be running to use this feature. * - * @note A stream must already be running to use this feature. + * @param[in] freq Desired frequency of tone. Off if set to 0. * - * @return -ENOMEM The frequency is too low (buffer overflow). - * @return 0 Success. + * @retval -ENOMEM The frequency is too low (buffer overflow). + * @retval 0 Success. */ int audio_system_encode_test_tone_set(uint32_t freq); /** - * @brief Step through different test tones. + * @brief Step through different test tones. * - * @note A stream must already be running to use this feature. - * Will step through test tones: 1 kHz, 2 kHz, 4 kHz and off. + * @note A stream must already be running to use this feature. + * Will step through test tones: 1 kHz, 2 kHz, 4 kHz and off. * - * @return 0 on success, error otherwise. + * @return 0 on success, error otherwise. */ int audio_system_encode_test_tone_step(void); /** - * @brief Decode data and then add it to TX FIFO buffer. + * @brief Set the sample rates for the encoder and the decoder, and the bit rate for encoder. + * + * @note If any of the values are 0, the corresponding configuration will not be set. + * + * @param[in] encoder_sample_rate_hz Sample rate to be used by the encoder; can be 0. + * @param[in] encoder_bitrate Bit rate to be used by the encoder (bps); can be 0. + * @param[in] decoder_sample_rate_hz Sample rate to be used by the decoder; can be 0. + * + * @retval -EINVAL Invalid sample rate given. + * @retval 0 On success. + */ +int audio_system_config_set(uint32_t encoder_sample_rate_hz, uint32_t encoder_bitrate, + uint32_t decoder_sample_rate_hz); + +/** + * @brief Decode data and then add it to TX FIFO buffer. * * @param[in] encoded_data Pointer to encoded data. * @param[in] encoded_data_size Size of encoded data. * @param[in] bad_frame Indication on missed or incomplete frame. * - * @return 0 on success, error otherwise. + * @return 0 on success, error otherwise. */ int audio_system_decode(void const *const encoded_data, size_t encoded_data_size, bool bad_frame); /** - * @brief Initialize and start both HW and SW audio codec. + * @brief Initialize and start both HW and SW audio codec. */ void audio_system_start(void); /** - * @brief Stop all activities related to audio. + * @brief Stop all activities related to audio. */ void audio_system_stop(void); /** - * @brief Drop oldest block from the fifo_rx buffer. + * @brief Drop oldest block from the fifo_rx buffer. * - * @note This can be used to reduce latency by adjusting the timing of the completed frame - * that was sampled in relation to the connection interval in Bluetooth LE. + * @note This can be used to reduce latency by adjusting the timing of the completed frame + * that was sampled in relation to the connection interval in Bluetooth LE. * - * @return 0 on success, -ECANCELED otherwise. + * @return 0 on success, -ECANCELED otherwise. */ int audio_system_fifo_rx_block_drop(void); /** - * @brief Get number of decoder channels + * @brief Get number of decoder channels. * - * @return Number of decoder channels + * @return Number of decoder channels. */ int audio_system_decoder_num_ch_get(void); /** - * @brief Initialize the audio_system + * @brief Initialize the audio_system. * - * @return 0 on success, error otherwise. + * @return 0 on success, error otherwise. */ int audio_system_init(void); diff --git a/applications/nrf5340_audio/src/audio/le_audio_rx.c b/applications/nrf5340_audio/src/audio/le_audio_rx.c index 479f49521cf..8c7c9370157 100644 --- a/applications/nrf5340_audio/src/audio/le_audio_rx.c +++ b/applications/nrf5340_audio/src/audio/le_audio_rx.c @@ -7,7 +7,6 @@ #include #include -#include "nrf5340_audio_common.h" #include "streamctrl.h" #include "audio_datapath.h" #include "macros_common.h" @@ -47,6 +46,8 @@ void le_audio_rx_data_handler(uint8_t const *const p_data, size_t data_size, boo uint32_t blocks_alloced_num, blocks_locked_num; struct ble_iso_data *iso_received = NULL; static struct rx_stats rx_stats[AUDIO_CH_NUM]; + static uint32_t num_overruns; + static uint32_t num_thrown; if (!initialized) { ERR_CHK_MSG(-EPERM, "Data received but le_audio_rx is not initialized"); @@ -78,7 +79,11 @@ void le_audio_rx_data_handler(uint8_t const *const p_data, size_t data_size, boo if (stream_state_get() != STATE_STREAMING) { /* Throw away data */ - LOG_WRN("Not in streaming state, throwing data: %d", stream_state_get()); + num_thrown++; + if ((num_thrown % 100) == 1) { + LOG_WRN("Not in streaming state (%d), thrown %d packet(s)", + stream_state_get(), num_thrown); + } return; } @@ -95,8 +100,11 @@ void le_audio_rx_data_handler(uint8_t const *const p_data, size_t data_size, boo void *stale_data; size_t stale_size; + num_overruns++; - LOG_WRN("BLE ISO RX overrun"); + if ((num_overruns % 100) == 1) { + LOG_WRN("BLE ISO RX overrun: Num: %d", num_overruns); + } ret = data_fifo_pointer_last_filled_get(&ble_fifo_rx, &stale_data, &stale_size, K_NO_WAIT); diff --git a/applications/nrf5340_audio/src/audio/streamctrl.h b/applications/nrf5340_audio/src/audio/streamctrl.h index 53da0d6995b..d96b7c91f4a 100644 --- a/applications/nrf5340_audio/src/audio/streamctrl.h +++ b/applications/nrf5340_audio/src/audio/streamctrl.h @@ -32,11 +32,4 @@ uint8_t stream_state_get(void); */ void streamctrl_send(void const *const data, size_t size, uint8_t num_ch); -/** - * @brief Initialize the internal functionality and start streamctrl. - * - * @return 0 if successful. - */ -int streamctrl_start(void); - #endif /* _STREAMCTRL_H_ */ diff --git a/applications/nrf5340_audio/src/audio/streamctrl_broadcast_sink.c b/applications/nrf5340_audio/src/audio/streamctrl_broadcast_sink.c deleted file mode 100644 index 2a21f0172c6..00000000000 --- a/applications/nrf5340_audio/src/audio/streamctrl_broadcast_sink.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "streamctrl.h" - -#include -#include - -#include "nrf5340_audio_common.h" -#include "broadcast_sink.h" -#include "led.h" -#include "button_assignments.h" -#include "macros_common.h" -#include "audio_system.h" -#include "bt_mgmt.h" -#include "bt_rend.h" -#include "audio_datapath.h" -#include "le_audio_rx.h" - -#include -LOG_MODULE_REGISTER(streamctrl_broadcast_sink, CONFIG_STREAMCTRL_LOG_LEVEL); - -struct ble_iso_data { - uint8_t data[CONFIG_BT_ISO_RX_MTU]; - size_t data_size; - bool bad_frame; - uint32_t sdu_ref; - uint32_t recv_frame_ts; -} __packed; - -ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); - -ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); - -ZBUS_CHAN_DECLARE(button_chan); -ZBUS_CHAN_DECLARE(le_audio_chan); -ZBUS_CHAN_DECLARE(bt_mgmt_chan); -ZBUS_CHAN_DECLARE(volume_chan); - -ZBUS_OBS_DECLARE(volume_evt_sub); - -static struct k_thread button_msg_sub_thread_data; -static struct k_thread le_audio_msg_sub_thread_data; - -static k_tid_t button_msg_sub_thread_id; -static k_tid_t le_audio_msg_sub_thread_id; - -K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); -K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); - -static enum stream_state strm_state = STATE_PAUSED; - -/* Function for handling all stream state changes */ -static void stream_state_set(enum stream_state stream_state_new) -{ - strm_state = stream_state_new; -} - -/** - * @brief Handle button activity. - */ -static void button_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - bool broadcast_alt = true; - - while (1) { - ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); - ERR_CHK(ret); - - struct button_msg msg; - - ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); - ERR_CHK(ret); - - LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, - msg.button_action); - - if (msg.button_action != BUTTON_PRESS) { - LOG_WRN("Unhandled button action"); - continue; - } - - switch (msg.button_pin) { - case BUTTON_PLAY_PAUSE: - if (strm_state == STATE_STREAMING) { - ret = broadcast_sink_stop(); - if (ret) { - LOG_WRN("Failed to stop broadcast sink: %d", ret); - } - } else if (strm_state == STATE_PAUSED) { - ret = broadcast_sink_start(); - if (ret) { - LOG_WRN("Failed to start broadcast sink: %d", ret); - } - } else { - LOG_WRN("In invalid state: %d", strm_state); - } - - break; - - case BUTTON_VOLUME_UP: - ret = bt_rend_volume_up(); - if (ret) { - LOG_WRN("Failed to increase volume: %d", ret); - } - - break; - - case BUTTON_VOLUME_DOWN: - ret = bt_rend_volume_down(); - if (ret) { - LOG_WRN("Failed to decrease volume: %d", ret); - } - - break; - - case BUTTON_4: - ret = broadcast_sink_change_active_audio_stream(); - if (ret) { - LOG_WRN("Failed to change active audio stream: %d", ret); - } - - break; - - case BUTTON_5: - if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { - ret = bt_rend_volume_mute(false); - if (ret) { - LOG_WRN("Failed to mute, ret: %d", ret); - } - - break; - } - - ret = broadcast_sink_disable(); - if (ret) { - LOG_ERR("Failed to disable the broadcast sink: %d", ret); - break; - } - - if (broadcast_alt) { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, - CONFIG_BT_AUDIO_BROADCAST_NAME_ALT); - broadcast_alt = false; - } else { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, - CONFIG_BT_AUDIO_BROADCAST_NAME); - broadcast_alt = true; - } - - if (ret) { - LOG_WRN("Failed to start scanning for broadcaster: %d", ret); - } - - break; - - default: - LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); - } - - STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); - } -} - -/** - * @brief Handle Bluetooth LE audio events. - */ -static void le_audio_msg_sub_thread(void) -{ - int ret; - uint32_t pres_delay_us; - uint32_t bitrate_bps; - uint32_t sampling_rate_hz; - - const struct zbus_channel *chan; - - while (1) { - struct le_audio_msg msg; - - ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); - ERR_CHK(ret); - - LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); - - switch (msg.event) { - case LE_AUDIO_EVT_STREAMING: - LOG_DBG("LE audio evt streaming"); - - if (strm_state == STATE_STREAMING) { - LOG_DBG("Got streaming event in streaming state"); - break; - } - - audio_system_start(); - stream_state_set(STATE_STREAMING); - ret = led_blink(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - case LE_AUDIO_EVT_NOT_STREAMING: - LOG_DBG("LE audio evt not_streaming"); - - if (strm_state == STATE_PAUSED) { - LOG_DBG("Got not_streaming event in paused state"); - break; - } - - stream_state_set(STATE_PAUSED); - audio_system_stop(); - ret = led_on(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - case LE_AUDIO_EVT_CONFIG_RECEIVED: - LOG_DBG("Config received"); - - ret = broadcast_sink_config_get(&bitrate_bps, &sampling_rate_hz, - &pres_delay_us); - if (ret) { - LOG_WRN("Failed to get config: %d", ret); - break; - } - - LOG_DBG("Sampling rate: %d Hz", sampling_rate_hz); - LOG_DBG("Bitrate: %d bps", bitrate_bps); - - ret = audio_datapath_pres_delay_us_set(pres_delay_us); - if (ret) { - LOG_ERR("Failed to set presentation delay to %d", pres_delay_us); - break; - } - - LOG_INF("Presentation delay %d us is set", pres_delay_us); - - break; - - case LE_AUDIO_EVT_SYNC_LOST: - LOG_INF("Sync lost"); - - ret = bt_mgmt_pa_sync_delete(msg.pa_sync); - if (ret) { - LOG_WRN("Failed to delete PA sync"); - } - - if (strm_state == STATE_STREAMING) { - stream_state_set(STATE_PAUSED); - audio_system_stop(); - ret = led_on(LED_APP_1_BLUE); - ERR_CHK(ret); - } - - if (IS_ENABLED(CONFIG_BT_OBSERVER)) { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL); - if (ret) { - if (ret == -EALREADY) { - break; - } - - LOG_ERR("Failed to restart scanning: %d", ret); - break; - } - - /* NOTE: The string below is used by the Nordic CI system */ - LOG_INF("Restarted scanning for broadcaster"); - } - - break; - - case LE_AUDIO_EVT_NO_VALID_CFG: - LOG_WRN("No valid configurations found, disabling the broadcast sink"); - - ret = broadcast_sink_disable(); - if (ret) { - LOG_ERR("Failed to disable the broadcast sink: %d", ret); - break; - } - - break; - - default: - LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); - - break; - } - - STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); - } -} - -/** - * @brief Create zbus subscriber threads. - * - * @return 0 for success, error otherwise. - */ -static int zbus_subscribers_create(void) -{ - int ret; - - button_msg_sub_thread_id = k_thread_create( - &button_msg_sub_thread_data, button_msg_sub_thread_stack, - CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create button_msg thread"); - return ret; - } - - le_audio_msg_sub_thread_id = k_thread_create( - &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, - CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create le_audio_msg thread"); - return ret; - } - - return 0; -} - -/** - * @brief Zbus listener to receive events from bt_mgmt. - * - * @param[in] chan Zbus channel. - * - * @note Will in most cases be called from BT_RX context, - * so there should not be too much processing done here. - */ -static void bt_mgmt_evt_handler(const struct zbus_channel *chan) -{ - int ret; - const struct bt_mgmt_msg *msg; - - msg = zbus_chan_const_msg(chan); - - switch (msg->event) { - case BT_MGMT_PA_SYNCED: - LOG_INF("PA synced"); - - ret = broadcast_sink_pa_sync_set(msg->pa_sync, msg->broadcast_id); - if (ret) { - LOG_WRN("Failed to set PA sync"); - } - - break; - - case BT_MGMT_PA_SYNC_LOST: - LOG_INF("PA sync lost, reason: %d", msg->pa_sync_term_reason); - - if (IS_ENABLED(CONFIG_BT_OBSERVER) && - msg->pa_sync_term_reason != BT_HCI_ERR_LOCALHOST_TERM_CONN) { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL); - if (ret) { - if (ret == -EALREADY) { - return; - } - - LOG_ERR("Failed to restart scanning: %d", ret); - break; - } - - /* NOTE: The string below is used by the Nordic CI system */ - LOG_INF("Restarted scanning for broadcaster"); - } - - break; - - default: - LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); - - break; - } -} - -ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); - -/** - * @brief Link zbus producers and observers. - * - * @return 0 for success, error otherwise. - */ -static int zbus_link_producers_observers(void) -{ - int ret; - - if (!IS_ENABLED(CONFIG_ZBUS)) { - return -ENOTSUP; - } - - ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add button sub"); - return ret; - } - - ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add le_audio sub"); - return ret; - } - - ret = zbus_chan_add_obs(&volume_chan, &volume_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add add volume sub"); - return ret; - } - - ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add bt_mgmt listener"); - return ret; - } - - return 0; -} - -uint8_t stream_state_get(void) -{ - return strm_state; -} - -void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) -{ - ARG_UNUSED(data); - ARG_UNUSED(size); - ARG_UNUSED(num_ch); - - LOG_WRN("Sending is not possible for broadcast sink"); -} - -int streamctrl_start(void) -{ - int ret; - static bool started; - - if (started) { - LOG_WRN("Streamctrl already started"); - return -EALREADY; - } - - ret = audio_system_init(); - ERR_CHK_MSG(ret, "Failed to initialize the audio system"); - - ret = zbus_subscribers_create(); - ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); - - ret = zbus_link_producers_observers(); - ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); - - ret = le_audio_rx_init(); - ERR_CHK_MSG(ret, "Failed to initialize rx path"); - - ret = broadcast_sink_enable(le_audio_rx_data_handler); - ERR_CHK_MSG(ret, "Failed to enable broadcast sink"); - - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, CONFIG_BT_AUDIO_BROADCAST_NAME); - ERR_CHK_MSG(ret, "Failed to start scanning"); - - started = true; - - return 0; -} diff --git a/applications/nrf5340_audio/src/audio/streamctrl_broadcast_source.c b/applications/nrf5340_audio/src/audio/streamctrl_broadcast_source.c deleted file mode 100644 index 22d830f2bfa..00000000000 --- a/applications/nrf5340_audio/src/audio/streamctrl_broadcast_source.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "streamctrl.h" - -#include -#include - -#include "nrf5340_audio_common.h" -#include "broadcast_source.h" -#include "led.h" -#include "button_assignments.h" -#include "macros_common.h" -#include "audio_system.h" -#include "bt_mgmt.h" - -#include -LOG_MODULE_REGISTER(streamctrl_brcast_src, CONFIG_STREAMCTRL_LOG_LEVEL); - -ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); - -ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); - -ZBUS_CHAN_DECLARE(button_chan); -ZBUS_CHAN_DECLARE(le_audio_chan); -ZBUS_CHAN_DECLARE(bt_mgmt_chan); -ZBUS_CHAN_DECLARE(sdu_ref_chan); - -ZBUS_OBS_DECLARE(sdu_ref_msg_listen); - -static struct k_thread button_msg_sub_thread_data; -static struct k_thread le_audio_msg_sub_thread_data; - -static k_tid_t button_msg_sub_thread_id; -static k_tid_t le_audio_msg_sub_thread_id; - -K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); -K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); - -static enum stream_state strm_state = STATE_PAUSED; - -/* Function for handling all stream state changes */ -static void stream_state_set(enum stream_state stream_state_new) -{ - strm_state = stream_state_new; -} - -/** - * @brief Handle button activity. - */ -static void button_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); - ERR_CHK(ret); - - struct button_msg msg; - - ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); - ERR_CHK(ret); - - LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, - msg.button_action); - - if (msg.button_action != BUTTON_PRESS) { - LOG_WRN("Unhandled button action"); - return; - } - - switch (msg.button_pin) { - case BUTTON_PLAY_PAUSE: - if (strm_state == STATE_STREAMING) { - ret = broadcast_source_stop(); - if (ret) { - LOG_WRN("Failed to stop broadcaster: %d", ret); - } - } else if (strm_state == STATE_PAUSED) { - ret = broadcast_source_start(NULL); - if (ret) { - LOG_WRN("Failed to start broadcaster: %d", ret); - } - } else { - LOG_WRN("In invalid state: %d", strm_state); - } - - break; - - case BUTTON_4: - if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { - if (strm_state != STATE_STREAMING) { - LOG_WRN("Not in streaming state"); - break; - } - - ret = audio_system_encode_test_tone_step(); - if (ret) { - LOG_WRN("Failed to play test tone, ret: %d", ret); - } - - break; - } - - break; - - default: - LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); - } - - STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); - } -} - -/** - * @brief Handle Bluetooth LE audio events. - */ -static void le_audio_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - struct le_audio_msg msg; - - ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); - ERR_CHK(ret); - - LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); - - switch (msg.event) { - case LE_AUDIO_EVT_STREAMING: - LOG_DBG("LE audio evt streaming"); - - if (strm_state == STATE_STREAMING) { - LOG_DBG("Got streaming event in streaming state"); - break; - } - - audio_system_start(); - stream_state_set(STATE_STREAMING); - ret = led_blink(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - case LE_AUDIO_EVT_NOT_STREAMING: - LOG_DBG("LE audio evt not_streaming"); - - if (strm_state == STATE_PAUSED) { - LOG_DBG("Got not_streaming event in paused state"); - break; - } - - stream_state_set(STATE_PAUSED); - audio_system_stop(); - ret = led_on(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - default: - LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); - - break; - } - - STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); - } -} - -/** - * @brief Create zbus subscriber threads. - * - * @return 0 for success, error otherwise. - */ -static int zbus_subscribers_create(void) -{ - int ret; - - button_msg_sub_thread_id = k_thread_create( - &button_msg_sub_thread_data, button_msg_sub_thread_stack, - CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create button_msg thread"); - return ret; - } - - le_audio_msg_sub_thread_id = k_thread_create( - &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, - CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create le_audio_msg thread"); - return ret; - } - - ret = zbus_chan_add_obs(&sdu_ref_chan, &sdu_ref_msg_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add timestamp listener"); - return ret; - } - - return 0; -} - -/** - * @brief Zbus listener to receive events from bt_mgmt. - * - * @param[in] chan Zbus channel. - * - * @note Will in most cases be called from BT_RX context, - * so there should not be too much processing done here. - */ -static void bt_mgmt_evt_handler(const struct zbus_channel *chan) -{ - int ret; - const struct bt_mgmt_msg *msg; - - msg = zbus_chan_const_msg(chan); - - switch (msg->event) { - case BT_MGMT_EXT_ADV_WITH_PA_READY: - LOG_INF("Ext adv ready"); - - ret = broadcast_source_start(msg->ext_adv); - if (ret) { - LOG_ERR("Failed to start broadcaster: %d", ret); - } - - break; - - default: - LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); - break; - } -} - -ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); - -/** - * @brief Link zbus producers and observers. - * - * @return 0 for success, error otherwise. - */ -static int zbus_link_producers_observers(void) -{ - int ret; - - if (!IS_ENABLED(CONFIG_ZBUS)) { - return -ENOTSUP; - } - - ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add button sub"); - return ret; - } - - ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add le_audio sub"); - return ret; - } - - ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add bt_mgmt listener"); - return ret; - } - - return 0; -} - -uint8_t stream_state_get(void) -{ - return strm_state; -} - -void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) -{ - int ret; - static int prev_ret; - - struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; - - if (strm_state == STATE_STREAMING) { - ret = broadcast_source_send(enc_audio); - - if (ret != 0 && ret != prev_ret) { - if (ret == -ECANCELED) { - LOG_WRN("Sending operation cancelled"); - } else { - LOG_WRN("Problem with sending LE audio data, ret: %d", ret); - } - } - - prev_ret = ret; - } -} - -int streamctrl_start(void) -{ - int ret; - static bool started; - - if (started) { - LOG_WRN("Streamctrl already started"); - return -EALREADY; - } - - size_t ext_adv_size = 0; - size_t per_adv_size = 0; - const struct bt_data *ext_adv = NULL; - const struct bt_data *per_adv = NULL; - - ret = audio_system_init(); - ERR_CHK_MSG(ret, "Failed to initialize the audio system"); - - ret = zbus_subscribers_create(); - ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); - - ret = zbus_link_producers_observers(); - ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); - - ret = broadcast_source_enable(); - ERR_CHK_MSG(ret, "Failed to enable broadcaster"); - - broadcast_source_adv_get(&ext_adv, &ext_adv_size, &per_adv, &per_adv_size); - - ret = bt_mgmt_adv_start(ext_adv, ext_adv_size, per_adv, per_adv_size, false); - ERR_CHK_MSG(ret, "Failed to start advertiser"); - - started = true; - - return 0; -} diff --git a/applications/nrf5340_audio/src/audio/streamctrl_unicast_client.c b/applications/nrf5340_audio/src/audio/streamctrl_unicast_client.c deleted file mode 100644 index b10741dee90..00000000000 --- a/applications/nrf5340_audio/src/audio/streamctrl_unicast_client.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "streamctrl.h" - -#include - -#include "nrf5340_audio_common.h" -#include "led.h" -#include "button_assignments.h" -#include "macros_common.h" -#include "audio_system.h" -#include "button_handler.h" -#include "le_audio.h" -#include "bt_mgmt.h" -#include "bt_rend.h" -#include "bt_content_ctrl.h" -#include "unicast_client.h" -#include "le_audio_rx.h" - -#include -LOG_MODULE_REGISTER(streamctrl_unicast_client, CONFIG_STREAMCTRL_LOG_LEVEL); - -static enum stream_state strm_state = STATE_PAUSED; - -ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); -ZBUS_SUBSCRIBER_DEFINE(content_control_evt_sub, CONFIG_CONTENT_CONTROL_MSG_SUB_QUEUE_SIZE); - -ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); - -ZBUS_CHAN_DECLARE(button_chan); -ZBUS_CHAN_DECLARE(le_audio_chan); -ZBUS_CHAN_DECLARE(bt_mgmt_chan); -ZBUS_CHAN_DECLARE(cont_media_chan); -ZBUS_CHAN_DECLARE(sdu_ref_chan); - -ZBUS_OBS_DECLARE(sdu_ref_msg_listen); - -static struct k_thread button_msg_sub_thread_data; -static struct k_thread le_audio_msg_sub_thread_data; -static struct k_thread content_control_msg_sub_thread_data; - -static k_tid_t button_msg_sub_thread_id; -static k_tid_t le_audio_msg_sub_thread_id; -static k_tid_t content_control_thread_id; - -K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); -K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); -K_THREAD_STACK_DEFINE(content_control_msg_sub_thread_stack, - CONFIG_CONTENT_CONTROL_MSG_SUB_STACK_SIZE); - -/* Function for handling all stream state changes */ -static void stream_state_set(enum stream_state stream_state_new) -{ - strm_state = stream_state_new; -} - -static void content_control_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - ret = zbus_sub_wait(&content_control_evt_sub, &chan, K_FOREVER); - ERR_CHK(ret); - - struct content_control_msg msg; - - ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); - ERR_CHK(ret); - - switch (msg.event) { - case MEDIA_START: - unicast_client_start(); - break; - - case MEDIA_STOP: - unicast_client_stop(); - break; - - default: - LOG_WRN("Unhandled event from content ctrl: %d", msg.event); - break; - } - - STACK_USAGE_PRINT("content_ctrl_msg_thread", &content_control_msg_sub_thread); - } -} - -/** - * @brief Handle button activity. - */ -static void button_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); - ERR_CHK(ret); - - struct button_msg msg; - - ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); - ERR_CHK(ret); - - LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, - msg.button_action); - - if (msg.button_action != BUTTON_PRESS) { - LOG_WRN("Unhandled button action"); - return; - } - - switch (msg.button_pin) { - case BUTTON_PLAY_PAUSE: - if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { - LOG_DBG("Play/pause not supported in walkie-talkie mode"); - break; - } - - if (strm_state == STATE_STREAMING) { - ret = bt_content_ctrl_stop(NULL); - if (ret) { - LOG_WRN("Could not stop: %d", ret); - } - - } else if (strm_state == STATE_PAUSED) { - ret = bt_content_ctrl_start(NULL); - if (ret) { - LOG_WRN("Could not start: %d", ret); - } - - } else { - LOG_WRN("In invalid state: %d", strm_state); - } - - break; - - case BUTTON_VOLUME_UP: - ret = bt_rend_volume_up(); - if (ret) { - LOG_WRN("Failed to increase volume: %d", ret); - } - - break; - - case BUTTON_VOLUME_DOWN: - ret = bt_rend_volume_down(); - if (ret) { - LOG_WRN("Failed to decrease volume: %d", ret); - } - - break; - - case BUTTON_4: - if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { - if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { - LOG_DBG("Test tone is disabled in walkie-talkie mode"); - break; - } - - if (strm_state != STATE_STREAMING) { - LOG_WRN("Not in streaming state"); - break; - } - - ret = audio_system_encode_test_tone_step(); - if (ret) { - LOG_WRN("Failed to play test tone, ret: %d", ret); - } - - break; - } - - break; - - case BUTTON_5: - if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { - ret = bt_rend_volume_mute(false); - if (ret) { - LOG_WRN("Failed to mute, ret: %d", ret); - } - - break; - } - - break; - - default: - LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); - } - - STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); - } -} - -/** - * @brief Handle Bluetooth LE audio events. - */ -static void le_audio_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - struct le_audio_msg msg; - - ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); - ERR_CHK(ret); - - LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); - - switch (msg.event) { - case LE_AUDIO_EVT_STREAMING: - LOG_DBG("LE audio evt streaming"); - - if (strm_state == STATE_STREAMING) { - LOG_DBG("Got streaming event in streaming state"); - break; - } - - audio_system_start(); - stream_state_set(STATE_STREAMING); - - ret = led_blink(LED_APP_1_BLUE); - ERR_CHK(ret); - break; - - case LE_AUDIO_EVT_NOT_STREAMING: - LOG_DBG("LE audio evt not_streaming"); - - if (strm_state == STATE_PAUSED) { - LOG_DBG("Got not_streaming event in paused state"); - break; - } - - stream_state_set(STATE_PAUSED); - audio_system_stop(); - - ret = led_on(LED_APP_1_BLUE); - ERR_CHK(ret); - break; - - default: - LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); - break; - } - - STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); - } -} - -/** - * @brief Zbus listener to receive events from bt_mgmt. - * - * @param[in] chan Zbus channel. - * - * @note Will in most cases be called from BT_RX context, - * so there should not be too much processing done here. - */ -static void bt_mgmt_evt_handler(const struct zbus_channel *chan) -{ - int ret; - const struct bt_mgmt_msg *msg; - - msg = zbus_chan_const_msg(chan); - - switch (msg->event) { - case BT_MGMT_CONNECTED: - LOG_INF("Device connected"); - break; - - case BT_MGMT_SECURITY_CHANGED: - LOG_INF("Security changed"); - - ret = bt_rend_discover(msg->conn); - if (ret) { - LOG_WRN("Failed to discover rendering services"); - } - - if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL)) { - ret = unicast_client_discover(msg->conn, UNICAST_SERVER_BIDIR); - } else { - ret = unicast_client_discover(msg->conn, UNICAST_SERVER_SINK); - } - - if (ret) { - LOG_ERR("Failed to handle unicast client discover: %d", ret); - } - - break; - - case BT_MGMT_DISCONNECTED: - LOG_INF("Device disconnected"); - - unicast_client_conn_disconnected(msg->conn); - break; - - default: - LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); - break; - } -} - -ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); - -/** - * @brief Create zbus subscriber threads. - * - * @return 0 for success, error otherwise. - */ -static int zbus_subscribers_create(void) -{ - int ret; - - button_msg_sub_thread_id = k_thread_create( - &button_msg_sub_thread_data, button_msg_sub_thread_stack, - CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create button_msg thread"); - return ret; - } - - le_audio_msg_sub_thread_id = k_thread_create( - &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, - CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create le_audio_msg thread"); - return ret; - } - - content_control_thread_id = k_thread_create( - &content_control_msg_sub_thread_data, content_control_msg_sub_thread_stack, - CONFIG_CONTENT_CONTROL_MSG_SUB_STACK_SIZE, - (k_thread_entry_t)content_control_msg_sub_thread, NULL, NULL, NULL, - K_PRIO_PREEMPT(CONFIG_CONTENT_CONTROL_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(content_control_thread_id, "CONTENT_CONTROL_MSG_SUB"); - if (ret) { - return ret; - } - - ret = zbus_chan_add_obs(&sdu_ref_chan, &sdu_ref_msg_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add timestamp listener"); - return ret; - } - - return 0; -} - -/** - * @brief Link zbus producers and observers. - * - * @return 0 for success, error otherwise. - */ -static int zbus_link_producers_observers(void) -{ - int ret; - - if (!IS_ENABLED(CONFIG_ZBUS)) { - return -ENOTSUP; - } - - ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add button sub"); - return ret; - } - - ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add le_audio sub"); - return ret; - } - - ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add bt_mgmt listener"); - return ret; - } - - ret = zbus_chan_add_obs(&cont_media_chan, &content_control_evt_sub, - ZBUS_ADD_OBS_TIMEOUT_MS); - - return 0; -} - -uint8_t stream_state_get(void) -{ - return strm_state; -} - -void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) -{ - int ret; - static int prev_ret; - - struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; - - if (strm_state == STATE_STREAMING) { - ret = unicast_client_send(enc_audio); - - if (ret != 0 && ret != prev_ret) { - if (ret == -ECANCELED) { - LOG_WRN("Sending operation cancelled"); - } else { - LOG_WRN("Problem with sending LE audio data, ret: %d", ret); - } - } - - prev_ret = ret; - } -} - -int streamctrl_start(void) -{ - int ret; - static bool started; - - if (started) { - LOG_WRN("Streamctrl already started"); - return -EALREADY; - } - - ret = audio_system_init(); - ERR_CHK_MSG(ret, "Failed to initialize the audio system"); - - ret = zbus_subscribers_create(); - ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); - - ret = zbus_link_producers_observers(); - ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); - - ret = le_audio_rx_init(); - ERR_CHK(ret); - - ret = bt_rend_init(); - ERR_CHK(ret); - - ret = bt_content_ctrl_init(); - ERR_CHK(ret); - - ret = unicast_client_enable(le_audio_rx_data_handler); - ERR_CHK(ret); - - started = true; - - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, CONFIG_BT_DEVICE_NAME); - if (ret) { - LOG_ERR("Failed to start scanning"); - return ret; - } - - return 0; -} diff --git a/applications/nrf5340_audio/src/audio/streamctrl_unicast_server.c b/applications/nrf5340_audio/src/audio/streamctrl_unicast_server.c deleted file mode 100644 index dcb91608356..00000000000 --- a/applications/nrf5340_audio/src/audio/streamctrl_unicast_server.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "streamctrl.h" - -#include - -#include "nrf5340_audio_common.h" -#include "led.h" -#include "button_assignments.h" -#include "macros_common.h" -#include "audio_system.h" -#include "button_handler.h" -#include "le_audio.h" -#include "bt_mgmt.h" -#include "bt_rend.h" -#include "audio_datapath.h" -#include "bt_content_ctrl.h" -#include "unicast_server.h" -#include "le_audio_rx.h" - -#include -LOG_MODULE_REGISTER(streamctrl_unicast_server, CONFIG_STREAMCTRL_LOG_LEVEL); - -ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); - -ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); - -ZBUS_CHAN_DECLARE(button_chan); -ZBUS_CHAN_DECLARE(le_audio_chan); -ZBUS_CHAN_DECLARE(bt_mgmt_chan); -ZBUS_CHAN_DECLARE(volume_chan); - -ZBUS_OBS_DECLARE(volume_evt_sub); - -static struct k_thread button_msg_sub_thread_data; -static struct k_thread le_audio_msg_sub_thread_data; - -static k_tid_t button_msg_sub_thread_id; -static k_tid_t le_audio_msg_sub_thread_id; - -K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); -K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); - -static enum stream_state strm_state = STATE_PAUSED; - -/* Function for handling all stream state changes */ -static void stream_state_set(enum stream_state stream_state_new) -{ - strm_state = stream_state_new; -} - -/** - * @brief Handle button activity. - */ -static void button_msg_sub_thread(void) -{ - int ret; - const struct zbus_channel *chan; - - while (1) { - ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); - ERR_CHK(ret); - - struct button_msg msg; - - ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); - ERR_CHK(ret); - - LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, - msg.button_action); - - if (msg.button_action != BUTTON_PRESS) { - LOG_WRN("Unhandled button action"); - return; - } - - switch (msg.button_pin) { - case BUTTON_PLAY_PAUSE: - if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { - LOG_DBG("Play/pause not supported in walkie-talkie mode"); - return; - } - - if (strm_state == STATE_STREAMING) { - ret = bt_content_ctrl_stop(NULL); - if (ret) { - LOG_WRN("Could not stop: %d", ret); - } - - } else if (strm_state == STATE_PAUSED) { - ret = bt_content_ctrl_start(NULL); - if (ret) { - LOG_WRN("Could not start: %d", ret); - } - - } else { - LOG_WRN("In invalid state: %d", strm_state); - } - - break; - - case BUTTON_VOLUME_UP: - ret = bt_rend_volume_up(); - if (ret) { - LOG_WRN("Failed to increase volume: %d", ret); - } - - break; - - case BUTTON_VOLUME_DOWN: - ret = bt_rend_volume_down(); - if (ret) { - LOG_WRN("Failed to decrease volume: %d", ret); - } - - break; - - case BUTTON_4: - if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { - if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { - LOG_DBG("Test tone is disabled in walkie-talkie mode"); - break; - } - - if (strm_state != STATE_STREAMING) { - LOG_WRN("Not in streaming state"); - break; - } - - ret = audio_system_encode_test_tone_step(); - if (ret) { - LOG_WRN("Failed to play test tone, ret: %d", ret); - } - - break; - } - - break; - - case BUTTON_5: - if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { - ret = bt_rend_volume_mute(false); - if (ret) { - LOG_WRN("Failed to mute, ret: %d", ret); - } - - break; - } - - break; - - default: - LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); - } - - STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); - } -} - -/** - * @brief Handle Bluetooth LE audio events. - */ -static void le_audio_msg_sub_thread(void) -{ - int ret; - uint32_t pres_delay_us; - uint32_t bitrate_bps; - uint32_t sampling_rate_hz; - const struct zbus_channel *chan; - - while (1) { - struct le_audio_msg msg; - - ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); - ERR_CHK(ret); - - LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); - - switch (msg.event) { - case LE_AUDIO_EVT_STREAMING: - LOG_DBG("LE audio evt streaming"); - - if (strm_state == STATE_STREAMING) { - LOG_DBG("Got streaming event in streaming state"); - break; - } - - audio_system_start(); - stream_state_set(STATE_STREAMING); - ret = led_blink(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - case LE_AUDIO_EVT_NOT_STREAMING: - LOG_DBG("LE audio evt not streaming"); - - if (strm_state == STATE_PAUSED) { - LOG_DBG("Got not_streaming event in paused state"); - break; - } - - stream_state_set(STATE_PAUSED); - audio_system_stop(); - ret = led_on(LED_APP_1_BLUE); - ERR_CHK(ret); - - break; - - case LE_AUDIO_EVT_CONFIG_RECEIVED: - LOG_DBG("Config received"); - - ret = unicast_server_config_get(&bitrate_bps, &sampling_rate_hz, NULL); - if (ret) { - LOG_WRN("Failed to get config: %d", ret); - break; - } - - LOG_DBG("Sampling rate: %d Hz", sampling_rate_hz); - LOG_DBG("Bitrate: %d bps", bitrate_bps); - - break; - - case LE_AUDIO_EVT_PRES_DELAY_SET: - LOG_DBG("Set presentation delay"); - - ret = unicast_server_config_get(NULL, NULL, &pres_delay_us); - if (ret) { - LOG_ERR("Failed to get config: %d", ret); - break; - } - - ret = audio_datapath_pres_delay_us_set(pres_delay_us); - if (ret) { - LOG_ERR("Failed to set presentation delay to %d", pres_delay_us); - break; - } - - LOG_INF("Presentation delay %d us is set by initiator", pres_delay_us); - - break; - - case LE_AUDIO_EVT_NO_VALID_CFG: - LOG_WRN("No valid configurations found, will disconnect"); - - ret = bt_mgmt_conn_disconnect(msg.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - if (ret) { - LOG_ERR("Failed to disconnect: %d", ret); - } - - break; - - default: - LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); - - break; - } - - STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); - } -} - -/** - * @brief Create zbus subscriber threads. - * - * @return 0 for success, error otherwise. - */ -static int zbus_subscribers_create(void) -{ - int ret; - - button_msg_sub_thread_id = k_thread_create( - &button_msg_sub_thread_data, button_msg_sub_thread_stack, - CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create button_msg thread"); - return ret; - } - - le_audio_msg_sub_thread_id = k_thread_create( - &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, - CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, - NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); - ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); - if (ret) { - LOG_ERR("Failed to create le_audio_msg thread"); - return ret; - } - - return 0; -} - -/** - * @brief Zbus listener to receive events from bt_mgmt. - * - * @param[in] chan Zbus channel. - * - * @note Will in most cases be called from BT_RX context, - * so there should not be too much processing done here. - */ -static void bt_mgmt_evt_handler(const struct zbus_channel *chan) -{ - int ret; - const struct bt_mgmt_msg *msg; - - msg = zbus_chan_const_msg(chan); - - switch (msg->event) { - case BT_MGMT_CONNECTED: - LOG_INF("Connected"); - - break; - - case BT_MGMT_DISCONNECTED: - LOG_INF("Disconnected"); - - ret = bt_content_ctrl_conn_disconnected(msg->conn); - if (ret) { - LOG_ERR("Failed to handle disconnection in content control: %d", ret); - } - - break; - - case BT_MGMT_SECURITY_CHANGED: - LOG_INF("Security changed"); - - ret = bt_rend_discover(msg->conn); - if (ret) { - LOG_WRN("Failed to discover rendering services"); - } - - ret = bt_content_ctrl_discover(msg->conn); - if (ret == -EALREADY) { - LOG_DBG("Discovery in progress or already done"); - } else if (ret) { - LOG_ERR("Failed to start discovery of content control: %d", ret); - } - - break; - - default: - LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); - - break; - } -} - -ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); - -/** - * @brief Link zbus producers and observers. - * - * @return 0 for success, error otherwise. - */ -static int zbus_link_producers_observers(void) -{ - int ret; - - if (!IS_ENABLED(CONFIG_ZBUS)) { - return -ENOTSUP; - } - - ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add button sub"); - return ret; - } - - ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add le_audio sub"); - return ret; - } - - ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add bt_mgmt sub"); - return ret; - } - - ret = zbus_chan_add_obs(&volume_chan, &volume_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); - if (ret) { - LOG_ERR("Failed to add volume sub"); - return ret; - } - - return 0; -} - -static int ext_adv_populate(struct bt_data *ext_adv_buf, size_t ext_adv_buf_size, - size_t *ext_adv_count) -{ - int ret; - size_t ext_adv_buf_cnt = 0; - - NET_BUF_SIMPLE_DEFINE(uuid_buf, CONFIG_EXT_ADV_UUID_BUF_MAX); - - ext_adv_buf[ext_adv_buf_cnt].type = BT_DATA_UUID16_SOME; - ext_adv_buf[ext_adv_buf_cnt].data_len = 0; - ext_adv_buf[ext_adv_buf_cnt].data = uuid_buf.data; - ext_adv_buf_cnt++; - - ret = bt_rend_uuid_populate(&uuid_buf); - - if (ret) { - LOG_ERR("Failed to add adv data from renderer: %d", ret); - return ret; - } - - ret = bt_content_ctrl_uuid_populate(&uuid_buf); - - if (ret) { - LOG_ERR("Failed to add adv data from content ctrl: %d", ret); - return ret; - } - - ret = unicast_server_adv_populate(&ext_adv_buf[ext_adv_buf_cnt], - ext_adv_buf_size - ext_adv_buf_cnt); - - if (ret < 0) { - LOG_ERR("Failed to add adv data from unicast server: %d", ret); - return ret; - } - - ext_adv_buf_cnt += ret; - - /* Add the number of UUIDs */ - ext_adv_buf[0].data_len = uuid_buf.len; - - LOG_DBG("Size of adv data: %d, num_elements: %d", sizeof(struct bt_data) * ext_adv_buf_cnt, - ext_adv_buf_cnt); - - *ext_adv_count = ext_adv_buf_cnt; - - return 0; -} - -uint8_t stream_state_get(void) -{ - return strm_state; -} - -void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) -{ - int ret; - static int prev_ret; - - struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; - - if (strm_state == STATE_STREAMING) { - ret = unicast_server_send(enc_audio); - - if (ret != 0 && ret != prev_ret) { - if (ret == -ECANCELED) { - LOG_WRN("Sending operation cancelled"); - } else { - LOG_WRN("Problem with sending LE audio data, ret: %d", ret); - } - } - - prev_ret = ret; - } -} - -int streamctrl_start(void) -{ - int ret; - static bool started; - struct bt_data ext_adv_buf[CONFIG_EXT_ADV_BUF_MAX]; - size_t ext_adv_buf_cnt = 0; - - if (started) { - LOG_WRN("Streamctrl already started"); - return -EALREADY; - } - - ret = audio_system_init(); - ERR_CHK(ret); - - ret = zbus_subscribers_create(); - ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); - - ret = zbus_link_producers_observers(); - ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); - - ret = le_audio_rx_init(); - ERR_CHK_MSG(ret, "Failed to initialize rx path"); - - ret = unicast_server_enable(le_audio_rx_data_handler); - ERR_CHK_MSG(ret, "Failed to enable LE Audio"); - - ret = bt_rend_init(); - ERR_CHK(ret); - - ret = bt_content_ctrl_init(); - ERR_CHK(ret); - - ret = ext_adv_populate(ext_adv_buf, ARRAY_SIZE(ext_adv_buf), &ext_adv_buf_cnt); - ERR_CHK(ret); - - ret = bt_mgmt_adv_start(ext_adv_buf, ext_adv_buf_cnt, NULL, 0, true); - ERR_CHK(ret); - - started = true; - - return 0; -} diff --git a/applications/nrf5340_audio/src/audio/sw_codec_select.c b/applications/nrf5340_audio/src/audio/sw_codec_select.c index 584e53b4fbc..ac3779330b7 100644 --- a/applications/nrf5340_audio/src/audio/sw_codec_select.c +++ b/applications/nrf5340_audio/src/audio/sw_codec_select.c @@ -11,6 +11,7 @@ #include "channel_assignment.h" #include "pcm_stream_channel_modifier.h" +#include "sample_rate_converter.h" #if (CONFIG_SW_CODEC_LC3) #include "sw_codec_lc3.h" #endif /* (CONFIG_SW_CODEC_LC3) */ @@ -20,6 +21,64 @@ LOG_MODULE_REGISTER(sw_codec_select, CONFIG_SW_CODEC_SELECT_LOG_LEVEL); static struct sw_codec_config m_config; +static struct sample_rate_converter_ctx encoder_converters[AUDIO_CH_NUM]; +static struct sample_rate_converter_ctx decoder_converters[AUDIO_CH_NUM]; + +/** + * @brief Converts the sample rate of the uncompressed audio stream if needed. + * + * @details Two buffers must be made available for the function: the input_data buffer that + * contains the samples for the audio stream, and the conversion buffer that will be + * used to store the converted audio stream. data_ptr will point to conversion_buffer + * if a conversion took place; otherwise, it will point to input_data. + * + * @param[in] ctx Sample rate converter context. + * @param[in] input_sample_rate Input sample rate. + * @param[in] output_sample_rate Output sample rate. + * @param[in] input_data Data coming in. Buffer is assumed to be of size + * PCM_NUM_BYTES_MONO. + * @param[in] input_data_size Size of input data. + * @param[in] conversion_buffer Buffer to perform sample rate conversion. Must be of size + * PCM_NUM_BYTES_MONO. + * @param[out] data_ptr Pointer to the data to be used from this point on. + * Will point to either @p input_data or @p conversion_buffer. + * @param[out] output_size Number of bytes out. + * + * @retval -ENOTSUP Sample rates are not equal, and the sample rate conversion has not + *been enabled in the application. + * @retval 0 Success. + */ +static int sw_codec_sample_rate_convert(struct sample_rate_converter_ctx *ctx, + uint32_t input_sample_rate, uint32_t output_sample_rate, + char *input_data, size_t input_data_size, + char *conversion_buffer, char **data_ptr, + size_t *output_size) +{ + int ret; + + if (input_sample_rate == output_sample_rate) { + *data_ptr = input_data; + *output_size = input_data_size; + } else if (IS_ENABLED(CONFIG_SAMPLE_RATE_CONVERTER)) { + ret = sample_rate_converter_process(ctx, SAMPLE_RATE_FILTER_SIMPLE, input_data, + input_data_size, input_sample_rate, + conversion_buffer, PCM_NUM_BYTES_MONO, + output_size, output_sample_rate); + if (ret) { + LOG_ERR("Failed to convert sample rate: %d", ret); + return ret; + } + + *data_ptr = conversion_buffer; + } else { + LOG_ERR("Sample rates are not equal, and sample rate conversion has not been " + "enabled in the application."); + return -ENOTSUP; + } + + return 0; +} + bool sw_codec_is_initialized(void) { return m_config.initialized; @@ -27,13 +86,17 @@ bool sw_codec_is_initialized(void) int sw_codec_encode(void *pcm_data, size_t pcm_size, uint8_t **encoded_data, size_t *encoded_size) { + int ret; + /* Temp storage for split stereo PCM signal */ - char pcm_data_mono[AUDIO_CH_NUM][PCM_NUM_BYTES_MONO] = {0}; + char pcm_data_mono_system_sample_rate[AUDIO_CH_NUM][PCM_NUM_BYTES_MONO] = {0}; /* Make sure we have enough space for two frames (stereo) */ static uint8_t m_encoded_data[ENC_MAX_FRAME_SIZE * AUDIO_CH_NUM]; + char pcm_data_mono_converted_buf[AUDIO_CH_NUM][PCM_NUM_BYTES_MONO] = {0}; + + size_t pcm_block_size_mono_system_sample_rate; size_t pcm_block_size_mono; - int ret; if (!m_config.encoder.enabled) { LOG_ERR("Encoder has not been initialized"); @@ -44,20 +107,36 @@ int sw_codec_encode(void *pcm_data, size_t pcm_size, uint8_t **encoded_data, siz case SW_CODEC_LC3: { #if (CONFIG_SW_CODEC_LC3) uint16_t encoded_bytes_written; + char *pcm_data_mono_ptrs[m_config.encoder.channel_mode]; /* Since LC3 is a single channel codec, we must split the * stereo PCM stream */ ret = pscm_two_channel_split(pcm_data, pcm_size, CONFIG_AUDIO_BIT_DEPTH_BITS, - pcm_data_mono[AUDIO_CH_L], pcm_data_mono[AUDIO_CH_R], - &pcm_block_size_mono); + pcm_data_mono_system_sample_rate[AUDIO_CH_L], + pcm_data_mono_system_sample_rate[AUDIO_CH_R], + &pcm_block_size_mono_system_sample_rate); if (ret) { return ret; } + for (int i = 0; i < m_config.encoder.channel_mode; ++i) { + ret = sw_codec_sample_rate_convert( + &encoder_converters[i], CONFIG_AUDIO_SAMPLE_RATE_HZ, + m_config.encoder.sample_rate_hz, + pcm_data_mono_system_sample_rate[i], + pcm_block_size_mono_system_sample_rate, + pcm_data_mono_converted_buf[i], &pcm_data_mono_ptrs[i], + &pcm_block_size_mono); + if (ret) { + LOG_ERR("Sample rate conversion failed for channel %d: %d", i, ret); + return ret; + } + } + switch (m_config.encoder.channel_mode) { case SW_CODEC_MONO: { - ret = sw_codec_lc3_enc_run(pcm_data_mono[m_config.encoder.audio_ch], + ret = sw_codec_lc3_enc_run(pcm_data_mono_ptrs[AUDIO_CH_L], pcm_block_size_mono, LC3_USE_BITRATE_FROM_INIT, 0, sizeof(m_encoded_data), m_encoded_data, &encoded_bytes_written); @@ -67,19 +146,19 @@ int sw_codec_encode(void *pcm_data, size_t pcm_size, uint8_t **encoded_data, siz break; } case SW_CODEC_STEREO: { - ret = sw_codec_lc3_enc_run(pcm_data_mono[AUDIO_CH_L], pcm_block_size_mono, - LC3_USE_BITRATE_FROM_INIT, AUDIO_CH_L, - sizeof(m_encoded_data), m_encoded_data, - &encoded_bytes_written); + ret = sw_codec_lc3_enc_run(pcm_data_mono_ptrs[AUDIO_CH_L], + pcm_block_size_mono, LC3_USE_BITRATE_FROM_INIT, + AUDIO_CH_L, sizeof(m_encoded_data), + m_encoded_data, &encoded_bytes_written); if (ret) { return ret; } - ret = sw_codec_lc3_enc_run(pcm_data_mono[AUDIO_CH_R], pcm_block_size_mono, - LC3_USE_BITRATE_FROM_INIT, AUDIO_CH_R, - sizeof(m_encoded_data) - encoded_bytes_written, - m_encoded_data + encoded_bytes_written, - &encoded_bytes_written); + ret = sw_codec_lc3_enc_run( + pcm_data_mono_ptrs[AUDIO_CH_R], pcm_block_size_mono, + LC3_USE_BITRATE_FROM_INIT, AUDIO_CH_R, + sizeof(m_encoded_data) - encoded_bytes_written, + m_encoded_data + encoded_bytes_written, &encoded_bytes_written); if (ret) { return ret; } @@ -115,28 +194,44 @@ int sw_codec_decode(uint8_t const *const encoded_data, size_t encoded_size, bool } int ret; - char pcm_data_mono[PCM_NUM_BYTES_MONO] = {0}; + static char pcm_data_stereo[PCM_NUM_BYTES_STEREO]; - uint16_t pcm_size_stereo = 0; - uint16_t pcm_size_session = 0; + char decoded_data_mono[AUDIO_CH_NUM][PCM_NUM_BYTES_MONO] = {0}; + char decoded_data_mono_system_sample_rate[AUDIO_CH_NUM][PCM_NUM_BYTES_MONO] = {0}; + + size_t pcm_size_stereo = 0; + size_t pcm_size_mono = 0; + size_t decoded_data_size = 0; switch (m_config.sw_codec) { case SW_CODEC_LC3: { #if (CONFIG_SW_CODEC_LC3) - /* Typically used for right channel if stereo signal */ - char pcm_data_mono_right[PCM_NUM_BYTES_MONO] = {0}; + char *pcm_in_data_ptrs[m_config.decoder.channel_mode]; switch (m_config.decoder.channel_mode) { case SW_CODEC_MONO: { if (bad_frame && IS_ENABLED(CONFIG_SW_CODEC_OVERRIDE_PLC)) { - memset(pcm_data_mono, 0, PCM_NUM_BYTES_MONO); - pcm_size_session = PCM_NUM_BYTES_MONO; + memset(decoded_data_mono[AUDIO_CH_L], 0, PCM_NUM_BYTES_MONO); + decoded_data_size = PCM_NUM_BYTES_MONO; } else { - ret = sw_codec_lc3_dec_run(encoded_data, encoded_size, - LC3_PCM_NUM_BYTES_MONO, 0, pcm_data_mono, - &pcm_size_session, bad_frame); + ret = sw_codec_lc3_dec_run( + encoded_data, encoded_size, LC3_PCM_NUM_BYTES_MONO, 0, + decoded_data_mono[AUDIO_CH_L], + (uint16_t *)&decoded_data_size, bad_frame); + if (ret) { + return ret; + } + + ret = sw_codec_sample_rate_convert( + &decoder_converters[AUDIO_CH_L], + m_config.decoder.sample_rate_hz, + CONFIG_AUDIO_SAMPLE_RATE_HZ, decoded_data_mono[AUDIO_CH_L], + decoded_data_size, + decoded_data_mono_system_sample_rate[AUDIO_CH_L], + &pcm_in_data_ptrs[AUDIO_CH_L], &pcm_size_mono); if (ret) { + LOG_ERR("Sample rate conversion failed for mono: %d", ret); return ret; } } @@ -145,9 +240,9 @@ int sw_codec_decode(uint8_t const *const encoded_data, size_t encoded_size, bool * just one channel, we need to insert 0 for the * other channel */ - ret = pscm_zero_pad(pcm_data_mono, (size_t)pcm_size_session, + ret = pscm_zero_pad(pcm_in_data_ptrs[AUDIO_CH_L], pcm_size_mono, m_config.decoder.audio_ch, CONFIG_AUDIO_BIT_DEPTH_BITS, - pcm_data_stereo, (size_t *)&pcm_size_stereo); + pcm_data_stereo, &pcm_size_stereo); if (ret) { return ret; } @@ -155,29 +250,50 @@ int sw_codec_decode(uint8_t const *const encoded_data, size_t encoded_size, bool } case SW_CODEC_STEREO: { if (bad_frame && IS_ENABLED(CONFIG_SW_CODEC_OVERRIDE_PLC)) { - memset(pcm_data_mono, 0, PCM_NUM_BYTES_MONO); - memset(pcm_data_mono_right, 0, PCM_NUM_BYTES_MONO); - pcm_size_session = PCM_NUM_BYTES_MONO; + memset(decoded_data_mono[AUDIO_CH_L], 0, PCM_NUM_BYTES_MONO); + memset(decoded_data_mono[AUDIO_CH_R], 0, PCM_NUM_BYTES_MONO); + decoded_data_size = PCM_NUM_BYTES_MONO; } else { /* Decode left channel */ ret = sw_codec_lc3_dec_run( encoded_data, encoded_size / 2, LC3_PCM_NUM_BYTES_MONO, - AUDIO_CH_L, pcm_data_mono, &pcm_size_session, bad_frame); + AUDIO_CH_L, decoded_data_mono[AUDIO_CH_L], + (uint16_t *)&decoded_data_size, bad_frame); if (ret) { return ret; } + /* Decode right channel */ - ret = sw_codec_lc3_dec_run((encoded_data + (encoded_size / 2)), - encoded_size / 2, LC3_PCM_NUM_BYTES_MONO, - AUDIO_CH_R, pcm_data_mono_right, - &pcm_size_session, bad_frame); + ret = sw_codec_lc3_dec_run( + (encoded_data + (encoded_size / 2)), encoded_size / 2, + LC3_PCM_NUM_BYTES_MONO, AUDIO_CH_R, + decoded_data_mono[AUDIO_CH_R], + (uint16_t *)&decoded_data_size, bad_frame); if (ret) { return ret; } + + for (int i = 0; i < m_config.decoder.channel_mode; ++i) { + ret = sw_codec_sample_rate_convert( + &decoder_converters[i], + m_config.decoder.sample_rate_hz, + CONFIG_AUDIO_SAMPLE_RATE_HZ, decoded_data_mono[i], + decoded_data_size, + decoded_data_mono_system_sample_rate[i], + &pcm_in_data_ptrs[i], &pcm_size_mono); + if (ret) { + LOG_ERR("Sample rate conversion failed for channel " + "%d : %d", + i, ret); + return ret; + } + } } - ret = pscm_combine(pcm_data_mono, pcm_data_mono_right, - (size_t)pcm_size_session, CONFIG_AUDIO_BIT_DEPTH_BITS, - pcm_data_stereo, (size_t *)&pcm_size_stereo); + + ret = pscm_combine(pcm_in_data_ptrs[AUDIO_CH_L], + pcm_in_data_ptrs[AUDIO_CH_R], pcm_size_mono, + CONFIG_AUDIO_BIT_DEPTH_BITS, pcm_data_stereo, + &pcm_size_stereo); if (ret) { return ret; } @@ -189,7 +305,7 @@ int sw_codec_decode(uint8_t const *const encoded_data, size_t encoded_size, bool return -ENODEV; } - *decoded_size = (size_t)pcm_size_stereo; + *decoded_size = pcm_size_stereo; *decoded_data = pcm_data_stereo; #endif /* (CONFIG_SW_CODEC_LC3) */ break; @@ -214,7 +330,8 @@ int sw_codec_uninit(struct sw_codec_config sw_codec_cfg) #if (CONFIG_SW_CODEC_LC3) if (sw_codec_cfg.encoder.enabled) { if (!m_config.encoder.enabled) { - LOG_ERR("Trying to uninit encoder, it has not been initialized"); + LOG_ERR("Trying to uninit encoder, it has not been " + "initialized"); return -EALREADY; } ret = sw_codec_lc3_enc_uninit_all(); @@ -226,7 +343,8 @@ int sw_codec_uninit(struct sw_codec_config sw_codec_cfg) if (sw_codec_cfg.decoder.enabled) { if (!m_config.decoder.enabled) { - LOG_WRN("Trying to uninit decoder, it has not been initialized"); + LOG_WRN("Trying to uninit decoder, it has not been " + "initialized"); return -EALREADY; } @@ -250,11 +368,11 @@ int sw_codec_uninit(struct sw_codec_config sw_codec_cfg) int sw_codec_init(struct sw_codec_config sw_codec_cfg) { + int ret; + switch (sw_codec_cfg.sw_codec) { case SW_CODEC_LC3: { #if (CONFIG_SW_CODEC_LC3) - int ret; - if (m_config.sw_codec != SW_CODEC_LC3) { /* Check if LC3 is already initialized */ ret = sw_codec_lc3_init(NULL, NULL, CONFIG_AUDIO_FRAME_DURATION_US); @@ -271,12 +389,12 @@ int sw_codec_init(struct sw_codec_config sw_codec_cfg) uint16_t pcm_bytes_req_enc; LOG_DBG("Encode: %dHz %dbits %dus %dbps %d channel(s)", - CONFIG_AUDIO_SAMPLE_RATE_HZ, CONFIG_AUDIO_BIT_DEPTH_BITS, + sw_codec_cfg.encoder.sample_rate_hz, CONFIG_AUDIO_BIT_DEPTH_BITS, CONFIG_AUDIO_FRAME_DURATION_US, sw_codec_cfg.encoder.bitrate, sw_codec_cfg.encoder.num_ch); ret = sw_codec_lc3_enc_init( - CONFIG_AUDIO_SAMPLE_RATE_HZ, CONFIG_AUDIO_BIT_DEPTH_BITS, + sw_codec_cfg.encoder.sample_rate_hz, CONFIG_AUDIO_BIT_DEPTH_BITS, CONFIG_AUDIO_FRAME_DURATION_US, sw_codec_cfg.encoder.bitrate, sw_codec_cfg.encoder.num_ch, &pcm_bytes_req_enc); @@ -292,11 +410,11 @@ int sw_codec_init(struct sw_codec_config sw_codec_cfg) } LOG_DBG("Decode: %dHz %dbits %dus %d channel(s)", - CONFIG_AUDIO_SAMPLE_RATE_HZ, CONFIG_AUDIO_BIT_DEPTH_BITS, + sw_codec_cfg.decoder.sample_rate_hz, CONFIG_AUDIO_BIT_DEPTH_BITS, CONFIG_AUDIO_FRAME_DURATION_US, sw_codec_cfg.decoder.num_ch); ret = sw_codec_lc3_dec_init( - CONFIG_AUDIO_SAMPLE_RATE_HZ, CONFIG_AUDIO_BIT_DEPTH_BITS, + sw_codec_cfg.decoder.sample_rate_hz, CONFIG_AUDIO_BIT_DEPTH_BITS, CONFIG_AUDIO_FRAME_DURATION_US, sw_codec_cfg.decoder.num_ch); if (ret) { @@ -305,7 +423,8 @@ int sw_codec_init(struct sw_codec_config sw_codec_cfg) } break; #else - LOG_ERR("LC3 is not compiled in, please open menuconfig and select LC3"); + LOG_ERR("LC3 is not compiled in, please open menuconfig and select " + "LC3"); return -ENODEV; #endif /* (CONFIG_SW_CODEC_LC3) */ } @@ -315,6 +434,30 @@ int sw_codec_init(struct sw_codec_config sw_codec_cfg) return false; } + if (sw_codec_cfg.encoder.enabled && IS_ENABLED(SAMPLE_RATE_CONVERTER)) { + for (int i = 0; i < sw_codec_cfg.encoder.channel_mode; i++) { + ret = sample_rate_converter_open(&encoder_converters[i]); + if (ret) { + LOG_ERR("Failed to initialize the sample rate converter for " + "encoding channel %d: %d", + i, ret); + return ret; + } + } + } + + if (sw_codec_cfg.decoder.enabled && IS_ENABLED(SAMPLE_RATE_CONVERTER)) { + for (int i = 0; i < sw_codec_cfg.decoder.channel_mode; i++) { + ret = sample_rate_converter_open(&decoder_converters[i]); + if (ret) { + LOG_ERR("Failed to initialize the sample rate converter for " + "decoding channel %d: %d", + i, ret); + return ret; + } + } + } + m_config = sw_codec_cfg; m_config.initialized = true; diff --git a/applications/nrf5340_audio/src/audio/sw_codec_select.h b/applications/nrf5340_audio/src/audio/sw_codec_select.h index 44d326946ac..3771fa79ae2 100644 --- a/applications/nrf5340_audio/src/audio/sw_codec_select.h +++ b/applications/nrf5340_audio/src/audio/sw_codec_select.h @@ -12,7 +12,7 @@ #if (CONFIG_SW_CODEC_LC3) #define LC3_MAX_FRAME_SIZE_MS 10 -#define LC3_ENC_MONO_FRAME_SIZE (CONFIG_LC3_BITRATE * LC3_MAX_FRAME_SIZE_MS / (8 * 1000)) +#define LC3_ENC_MONO_FRAME_SIZE (CONFIG_LC3_BITRATE_MAX * LC3_MAX_FRAME_SIZE_MS / (8 * 1000)) #define LC3_PCM_NUM_BYTES_MONO \ (CONFIG_AUDIO_SAMPLE_RATE_HZ * CONFIG_AUDIO_BIT_DEPTH_OCTETS * LC3_MAX_FRAME_SIZE_MS / 1000) @@ -48,6 +48,7 @@ struct sw_codec_encoder { enum sw_codec_channel_mode channel_mode; uint8_t num_ch; enum audio_channel audio_ch; + uint32_t sample_rate_hz; }; struct sw_codec_decoder { @@ -55,6 +56,7 @@ struct sw_codec_decoder { enum sw_codec_channel_mode channel_mode; /* Mono or stereo. */ uint8_t num_ch; /* Number of decoder channels. */ enum audio_channel audio_ch; /* Used to choose which channel to use. */ + uint32_t sample_rate_hz; }; /** diff --git a/applications/nrf5340_audio/src/bluetooth/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/CMakeLists.txt index c180f299790..42a4f65e113 100644 --- a/applications/nrf5340_audio/src/bluetooth/CMakeLists.txt +++ b/applications/nrf5340_audio/src/bluetooth/CMakeLists.txt @@ -5,13 +5,13 @@ # add_subdirectory(bt_management) -add_subdirectory(bt_renderer) +add_subdirectory(bt_rendering_and_capture) add_subdirectory(bt_content_control) add_subdirectory(bt_stream) zephyr_library_include_directories( bt_management - bt_renderer + bt_rendering_and_capture bt_content_control bt_stream ) diff --git a/applications/nrf5340_audio/src/bluetooth/Kconfig b/applications/nrf5340_audio/src/bluetooth/Kconfig index 44c0133caaf..fea6769527f 100644 --- a/applications/nrf5340_audio/src/bluetooth/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/Kconfig @@ -27,6 +27,43 @@ config BT_AUDIO_PACKING_INTERLEAVED help ISO channels can either be interleaved or sequentially packed; sequential is the default one. +config BT_AUDIO_PREF_SAMPLE_RATE_VALUE + hex + default 0x03 if BT_AUDIO_PREF_SAMPLE_RATE_16KHZ + default 0x05 if BT_AUDIO_PREF_SAMPLE_RATE_24KHZ + default 0x08 if BT_AUDIO_PREF_SAMPLE_RATE_48KHZ + +choice BT_AUDIO_PREF_SAMPLE_RATE + prompt "Preferred BT audio sample rate" + default BT_AUDIO_PREF_SAMPLE_RATE_16KHZ if BT_BAP_BROADCAST_16_2_1 + default BT_AUDIO_PREF_SAMPLE_RATE_16KHZ if BT_BAP_BROADCAST_16_2_2 + default BT_AUDIO_PREF_SAMPLE_RATE_16KHZ if BT_BAP_UNICAST_16_2_1 + default BT_AUDIO_PREF_SAMPLE_RATE_24KHZ if STREAM_BIDIRECTIONAL + default BT_AUDIO_PREF_SAMPLE_RATE_24KHZ if BT_BAP_BROADCAST_24_2_1 + default BT_AUDIO_PREF_SAMPLE_RATE_24KHZ if BT_BAP_BROADCAST_24_2_2 + default BT_AUDIO_PREF_SAMPLE_RATE_24KHZ if BT_BAP_UNICAST_24_2_1 + default BT_AUDIO_PREF_SAMPLE_RATE_48KHZ + help + Select the preferred sample rate to stream if there are more than one to choose from. + Only valid when used by unicast_client if CONFIG_SAMPLE_RATE_CONVERTER=y and + CONFIG_AUDIO_SAMPLE_RATE_48000_HZ=y, meaning 16, 24, and 48kHz are supported. + +config BT_AUDIO_PREF_SAMPLE_RATE_48KHZ + bool "48 kHz" + help + Select 48000 Hz as the preferred sample rate. + +config BT_AUDIO_PREF_SAMPLE_RATE_24KHZ + bool "24 kHz" + help + Select 24000 Hz as the preferred sample rate. + +config BT_AUDIO_PREF_SAMPLE_RATE_16KHZ + bool "16 kHz" + help + Select 16000 Hz as the preferred sample rate. +endchoice + #----------------------------------------------------------------------------# menu "QoS" @@ -50,17 +87,17 @@ config BT_AUDIO_MAX_TRANSPORT_LATENCY_MS Max transport latency for the ISO link. config BT_AUDIO_RETRANSMITS - int "Number of retransmits" + int "Number of re-transmits" range 0 30 default 2 help - Number of retransmits for the ISO link. 2 retransmits means a total + Number of re-transmits for the ISO link. 2 re-transmits means a total of 3 packets sent per stream. endmenu # QoS endmenu # Bluetooth audio -rsource "bt_renderer/Kconfig" +rsource "bt_rendering_and_capture/Kconfig" rsource "bt_content_control/Kconfig" #----------------------------------------------------------------------------# @@ -71,4 +108,18 @@ module-str = ble source "subsys/logging/Kconfig.template.log_config" endmenu # Log levels + +#----------------------------------------------------------------------------# +menu "Testing" + +config TESTING_BLE_ADDRESS_RANDOM + bool "Random address and bonding clear on every restart [EXPERIMENTAL]" + default n + select EXPERIMENTAL + help + If enabled the system will generate a new address on every + restart (i.e. reset, re-flash). Any bonding information will + be cleared. This is only for testing purposes. + +endmenu # Testing endmenu # Bluetooth diff --git a/applications/nrf5340_audio/src/bluetooth/Kconfig.defaults b/applications/nrf5340_audio/src/bluetooth/Kconfig.defaults index 0154c16b797..288acd5645c 100644 --- a/applications/nrf5340_audio/src/bluetooth/Kconfig.defaults +++ b/applications/nrf5340_audio/src/bluetooth/Kconfig.defaults @@ -8,6 +8,7 @@ config BT_AUDIO default y config BT_DEVICE_NAME + default BT_AUDIO_BROADCAST_NAME if TRANSPORT_BIS default "NRF5340_AUDIO" config BT_ECC diff --git a/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.c b/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.c index 6214a2453d7..484393721bc 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.c @@ -86,7 +86,10 @@ int bt_content_ctrl_conn_disconnected(struct bt_conn *conn) if (IS_ENABLED(CONFIG_BT_MCC)) { ret = bt_content_ctrl_media_conn_disconnected(conn); - if (ret) { + /* Try to reset MCS state. -ESRCH is returned if MCS hasn't been discovered + * yet, and shouldn't cause an error print + */ + if (ret && ret != -ESRCH) { LOG_ERR("bt_content_ctrl_media_conn_disconnected failed with %d", ret); } } diff --git a/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.h b/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.h index 67038a28dee..805dedc8fa5 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_content_control/bt_content_ctrl.h @@ -56,6 +56,14 @@ int bt_content_ctrl_discover(struct bt_conn *conn); */ int bt_content_ctrl_uuid_populate(struct net_buf_simple *uuid_buf); +/** + * @brief Check if the media player is playing. + * + * @retval true Media player is in a playing state. + * @retval false Media player is not in a playing state. + */ +bool bt_content_ctlr_media_state_playing(void); + /** * @brief Initialize the content control module. * diff --git a/applications/nrf5340_audio/src/bluetooth/bt_content_control/media/bt_content_ctrl_media.c b/applications/nrf5340_audio/src/bluetooth/bt_content_control/media/bt_content_ctrl_media.c index 370e8ad6973..de090822bf2 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_content_control/media/bt_content_ctrl_media.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_content_control/media/bt_content_ctrl_media.c @@ -128,6 +128,7 @@ static void mcc_discover_mcs_cb(struct bt_conn *conn, int err) } } +#if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) /** * @brief Callback handler for sent MCS commands. * @@ -143,6 +144,7 @@ static void mcc_send_command_cb(struct bt_conn *conn, int err, const struct mpl_ cmd->param); } } +#endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */ /** * @brief Callback handler for received notifications. @@ -160,6 +162,7 @@ static void mcc_cmd_notification_cb(struct bt_conn *conn, int err, const struct } } +#if defined(CONFIG_BT_MCC_READ_MEDIA_STATE) /** * @brief Callback handler for reading media state. * @@ -177,6 +180,7 @@ static void mcc_read_media_state_cb(struct bt_conn *conn, int err, uint8_t state media_player_state = state; } +#endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */ /** * @brief Callback handler for received MCS commands. @@ -438,6 +442,15 @@ int bt_content_ctrl_media_pause(struct bt_conn *conn) return 0; } +bool bt_content_ctlr_media_state_playing(void) +{ + if (media_player_state == BT_MCS_MEDIA_STATE_PLAYING) { + return true; + } + + return false; +} + int bt_content_ctrl_media_conn_disconnected(struct bt_conn *conn) { int idx = mcc_peer_index_get(conn); @@ -463,9 +476,13 @@ int bt_content_ctrl_media_client_init(void) static struct bt_mcc_cb mcc_cb; mcc_cb.discover_mcs = mcc_discover_mcs_cb; +#if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) mcc_cb.send_cmd = mcc_send_command_cb; +#endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */ mcc_cb.cmd_ntf = mcc_cmd_notification_cb; +#if defined(CONFIG_BT_MCC_READ_MEDIA_STATE) mcc_cb.read_media_state = mcc_read_media_state_cb; +#endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */ return bt_mcc_init(&mcc_cb); } diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/bt_management/CMakeLists.txt index 5c2bc81cabe..5076f3ff05c 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/CMakeLists.txt +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_include_directories( controller_config dfu scanning + ${ZEPHYR_BASE}/subsys/bluetooth/host/ ) target_sources(app PRIVATE diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_management/Kconfig index 5f526a188b4..23de1818d36 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/Kconfig @@ -154,6 +154,17 @@ config BLE_ADV_TX_POWER_DBM endmenu # Power control +menu "Thread priorities" + +config CTLR_POLL_WORK_Q_PRIO + int "Work queue priority for controller poll" + default 6 + help + This is a preemptible work queue. + This work queue will poll the controller to check it is alive. + +endmenu # Thread priorities + rsource "dfu/Kconfig" rsource "advertising/Kconfig" rsource "scanning/Kconfig" diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/Kconfig index 0f89f3fe021..038ba36e681 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/Kconfig @@ -48,11 +48,24 @@ config BLE_ACL_EXT_ADV_INT_MAX config EXT_ADV_BUF_MAX int "Maximum number of extended advertising data parameters" - default 10 + default 20 config EXT_ADV_UUID_BUF_MAX int "Maximum number of UUIDs to add to extended advertisements" - default 10 + default 20 + +config BT_DEVICE_MANUFACTURER_ID + hex "Manufacturer ID" + default 0xFE58 + help + Bluetooth manufacturer ID. For the list of possible values please + consult the following link: + https://www.bluetooth.com/specifications/assigned-numbers + +config BLE_ACL_ADV_SID + hex "Advertising set ID" + range 0x00 0x0F + default 0x00 #----------------------------------------------------------------------------# menu "Log level" diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv.c b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv.c index c956418d796..0d241f97143 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv.c @@ -25,18 +25,27 @@ ZBUS_CHAN_DECLARE(bt_mgmt_chan); #endif static struct k_work adv_work; - +static bool dir_adv_timed_out; static struct bt_le_ext_adv *ext_adv; static const struct bt_data *adv_local; static size_t adv_local_size; - static const struct bt_data *per_adv_local; static size_t per_adv_local_size; /* Bonded address queue */ K_MSGQ_DEFINE(bonds_queue, sizeof(bt_addr_le_t), BONDS_QUEUE_SIZE, 4); +static struct bt_le_adv_param ext_adv_param = { + .id = BT_ID_DEFAULT, + .sid = CONFIG_BLE_ACL_ADV_SID, + .secondary_max_skip = 0, + .options = BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_NAME, + .interval_min = CONFIG_BLE_ACL_EXT_ADV_INT_MIN, + .interval_max = CONFIG_BLE_ACL_EXT_ADV_INT_MAX, + .peer = NULL, +}; + static void bond_find(const struct bt_bond_info *info, void *user_data) { int ret; @@ -73,6 +82,17 @@ static void bond_find(const struct bt_bond_info *info, void *user_data) } } +static void filter_accept_list_add(const struct bt_bond_info *info, void *user_data) +{ + int ret; + + ret = bt_le_filter_accept_list_add(&info->addr); + if (ret) { + LOG_WRN("Could not add peer to Filter Accept List: %d", ret); + return; + } +} + /** * @brief Prints the address of the local device and the remote device. * @@ -127,12 +147,11 @@ static const struct bt_le_ext_adv_cb adv_cb = { static int direct_adv_create(bt_addr_le_t addr) { int ret; - struct bt_le_adv_param adv_param; struct bt_le_ext_adv_info ext_adv_info; - adv_param = *BT_LE_ADV_CONN_DIR_LOW_DUTY(&addr); - adv_param.id = BT_ID_DEFAULT; - adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; + ext_adv_param = *BT_LE_ADV_CONN_DIR(&addr); + ext_adv_param.id = BT_ID_DEFAULT; + ext_adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; /* Clear ADV data set before update to direct advertising */ ret = bt_le_ext_adv_set_data(ext_adv, NULL, 0, NULL, 0); @@ -141,7 +160,7 @@ static int direct_adv_create(bt_addr_le_t addr) return ret; } - ret = bt_le_ext_adv_update_param(ext_adv, &adv_param); + ret = bt_le_ext_adv_update_param(ext_adv, &ext_adv_param); if (ret) { LOG_ERR("Failed to update ext_adv to direct advertising. Err = %d", ret); return ret; @@ -213,25 +232,41 @@ static void advertising_process(struct k_work *work) if (IS_ENABLED(CONFIG_BT_BONDABLE)) { bt_foreach_bond(BT_ID_DEFAULT, bond_find, NULL); + /* Populate Filter Accept List */ + if (IS_ENABLED(CONFIG_BT_FILTER_ACCEPT_LIST)) { + ret = bt_le_filter_accept_list_clear(); + if (ret) { + LOG_ERR("Failed to clear filter accept list"); + return; + } + + bt_foreach_bond(BT_ID_DEFAULT, filter_accept_list_add, NULL); + } } bt_addr_le_t addr; - if (!k_msgq_get(&bonds_queue, &addr, K_NO_WAIT)) { + if (!k_msgq_get(&bonds_queue, &addr, K_NO_WAIT) && !dir_adv_timed_out) { ret = direct_adv_create(addr); if (ret) { LOG_WRN("Failed to create direct advertisement: %d", ret); return; } + + ret = bt_le_ext_adv_start( + ext_adv, + BT_LE_EXT_ADV_START_PARAM(BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT, 0)); } else { ret = extended_adv_create(); if (ret) { LOG_WRN("Failed to create extended advertisement: %d", ret); return; } + + dir_adv_timed_out = false; + ret = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); } - ret = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); if (ret) { LOG_ERR("Failed to start advertising set. Err: %d", ret); return; @@ -256,6 +291,46 @@ static void advertising_process(struct k_work *work) LOG_INF("Advertising successfully started"); } +void bt_mgmt_dir_adv_timed_out(void) +{ + int ret; + + dir_adv_timed_out = true; + + LOG_DBG("Clearing ext_adv"); + + ret = bt_le_ext_adv_delete(ext_adv); + if (ret) { + LOG_ERR("Failed to clear ext_adv"); + } + + if (IS_ENABLED(CONFIG_BT_FILTER_ACCEPT_LIST)) { + ret = bt_le_ext_adv_create(LE_AUDIO_EXTENDED_ADV_CONN_NAME_FILTER, &adv_cb, + &ext_adv); + } else { + ret = bt_le_ext_adv_create(LE_AUDIO_EXTENDED_ADV_CONN_NAME, &adv_cb, &ext_adv); + } + + if (ret) { + LOG_ERR("Unable to create a connectable extended advertising set: %d", ret); + return; + } + + /* Restart normal advertising */ + bt_mgmt_adv_start(NULL, 0, NULL, 0, true); +} + +int bt_mgmt_manufacturer_uuid_populate(struct net_buf_simple *uuid_buf, uint16_t company_id) +{ + if (net_buf_simple_tailroom(uuid_buf) >= BT_UUID_SIZE_16) { + net_buf_simple_add_le16(uuid_buf, company_id); + } else { + return -ENOMEM; + } + + return 0; +} + int bt_mgmt_adv_start(const struct bt_data *adv, size_t adv_size, const struct bt_data *per_adv, size_t per_adv_size, bool connectable) { @@ -295,7 +370,7 @@ int bt_mgmt_adv_start(const struct bt_data *adv, size_t adv_size, const struct b return ret; } } else { - ret = bt_le_ext_adv_create(LE_AUDIO_EXTENDED_ADV_NAME, &adv_cb, &ext_adv); + ret = bt_le_ext_adv_create(&ext_adv_param, &adv_cb, &ext_adv); if (ret) { LOG_ERR("Unable to create extended advertising set: %d", ret); return ret; diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv_internal.h b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv_internal.h index 5440a2a5fcb..acb40251b62 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv_internal.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/advertising/bt_mgmt_adv_internal.h @@ -14,4 +14,12 @@ */ void bt_mgmt_adv_init(void); +/** + * @brief Handle timed-out directed advertisement. + * + * This function deletes the old ext_adv and creates a new one. + * It also sets the dir_adv_timed_out flag and restarts advertisement. + */ +void bt_mgmt_dir_adv_timed_out(void); + #endif /* _BT_MGMT_ADV_INTERNAL_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.c b/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.c index 9dd76397d92..3f486f313cf 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.c @@ -24,10 +24,6 @@ #include "bt_mgmt_dfu_internal.h" #endif -#if (CONFIG_BT_LL_ACS_NRF53) -#include "ble_hci_vsc.h" -#endif /* (CONFIG_BT_LL_ACS_NRF53) */ - #include LOG_MODULE_REGISTER(bt_mgmt, CONFIG_BT_MGMT_LOG_LEVEL); @@ -79,6 +75,19 @@ static void connected_cb(struct bt_conn *conn, uint8_t err) uint8_t num_conn = 0; struct bt_mgmt_msg msg; + if (err == BT_HCI_ERR_ADV_TIMEOUT && IS_ENABLED(CONFIG_BT_PERIPHERAL)) { + LOG_INF("Directed adv timed out with no connection, reverting to normal adv"); + + bt_mgmt_dir_adv_timed_out(); + + ret = bt_mgmt_adv_start(NULL, 0, NULL, 0, true); + if (ret) { + LOG_ERR("Failed to restart advertising: %d", ret); + } + + return; + } + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); if (err) { @@ -88,8 +97,9 @@ static void connected_cb(struct bt_conn *conn, uint8_t err) bt_conn_unref(conn); if (IS_ENABLED(CONFIG_BT_CENTRAL)) { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL); - if (ret) { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL, + BRDCAST_ID_NOT_USED); + if (ret && ret != -EALREADY) { LOG_ERR("Failed to restart scanning: %d", ret); } } @@ -112,36 +122,12 @@ static void connected_cb(struct bt_conn *conn, uint8_t err) if (IS_ENABLED(CONFIG_BT_CENTRAL) && (num_conn < MAX_CONN_NUM)) { /* Room for more connections, start scanning again */ - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL); + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL, BRDCAST_ID_NOT_USED); if (ret) { LOG_ERR("Failed to resume scanning: %d", ret); } } -#if (CONFIG_BT_LL_ACS_NRF53) - enum ble_hci_vs_tx_power conn_tx_pwr; - uint16_t conn_handle; - - ret = bt_hci_get_conn_handle(conn, &conn_handle); - if (ret) { - LOG_ERR("Unable to get conn handle"); - } else { - if (IS_ENABLED(CONFIG_NRF_21540_ACTIVE)) { - conn_tx_pwr = CONFIG_NRF_21540_MAIN_DBM; - } else { - conn_tx_pwr = CONFIG_BLE_CONN_TX_POWER_DBM; - } - - ret = ble_hci_vsc_conn_tx_pwr_set(conn_handle, conn_tx_pwr); - if (ret) { - LOG_ERR("Failed to set TX power for conn"); - } else { - LOG_DBG("TX power set to %d dBm for connection %p", conn_tx_pwr, - (void *)conn); - } - } -#endif /* (CONFIG_BT_LL_ACS_NRF53) */ - msg.event = BT_MGMT_CONNECTED; msg.conn = conn; @@ -156,6 +142,8 @@ static void connected_cb(struct bt_conn *conn, uint8_t err) } } +K_MUTEX_DEFINE(mtx_duplicate_scan); + static void disconnected_cb(struct bt_conn *conn, uint8_t reason) { int ret; @@ -183,12 +171,18 @@ static void disconnected_cb(struct bt_conn *conn, uint8_t reason) ERR_CHK(ret); } + /* The mutex for preventing the racing condition if two headset disconnected too close, + * cause the disconnected_cb() triggered in short time leads to duplicate scanning + * operation. + */ + k_mutex_lock(&mtx_duplicate_scan, K_FOREVER); if (IS_ENABLED(CONFIG_BT_CENTRAL)) { - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL); - if (ret) { + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL, BRDCAST_ID_NOT_USED); + if (ret && ret != -EALREADY) { LOG_ERR("Failed to restart scanning: %d", ret); } } + k_mutex_unlock(&mtx_duplicate_scan); } #if defined(CONFIG_BT_SMP) @@ -198,10 +192,10 @@ static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum struct bt_mgmt_msg msg; if (err) { - LOG_ERR("Security failed: level %d err %d", level, err); - ret = bt_conn_disconnect(conn, err); + LOG_WRN("Security failed: level %d err %d", level, err); + ret = bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); if (ret) { - LOG_ERR("Failed to disconnect %d", ret); + LOG_WRN("Failed to disconnect %d", ret); } } else { LOG_DBG("Security changed: level %d", level); @@ -249,10 +243,11 @@ static int bonding_clear_check(void) ret = bt_mgmt_bonding_clear(); return ret; } + return 0; } -static int random_static_addr_cfg(void) +static int ficr_static_addr_set(void) { int ret; static bt_addr_le_t addr; @@ -288,6 +283,27 @@ static int random_static_addr_cfg(void) return 0; } +/* This function generates a random address for bonding testing */ +static int random_static_addr_set(void) +{ + int ret; + static bt_addr_le_t addr; + + ret = bt_addr_le_create_static(&addr); + if (ret < 0) { + LOG_ERR("Failed to create address %d", ret); + return ret; + } + + ret = bt_id_create(&addr, NULL); + if (ret < 0) { + LOG_ERR("Failed to create ID %d", ret); + return ret; + } + + return 0; +} + static int local_identity_addr_print(void) { size_t num_ids = 0; @@ -369,7 +385,7 @@ int bt_mgmt_init(void) int ret; if (!IS_ENABLED(CONFIG_BT_PRIVACY)) { - ret = random_static_addr_cfg(); + ret = ficr_static_addr_set(); if (ret) { return ret; } @@ -386,6 +402,13 @@ int bt_mgmt_init(void) return ret; } + if (IS_ENABLED(CONFIG_TESTING_BLE_ADDRESS_RANDOM)) { + ret = random_static_addr_set(); + if (ret) { + return ret; + } + } + if (IS_ENABLED(CONFIG_SETTINGS)) { ret = settings_load(); if (ret) { @@ -396,6 +419,13 @@ int bt_mgmt_init(void) if (ret) { return ret; } + + if (IS_ENABLED(CONFIG_TESTING_BLE_ADDRESS_RANDOM)) { + ret = bt_mgmt_bonding_clear(); + if (ret) { + return ret; + } + } } #if defined(CONFIG_AUDIO_DFU_ENABLE) @@ -415,6 +445,7 @@ int bt_mgmt_init(void) bt_mgmt_dfu_start(); } #endif + ret = bt_mgmt_ctlr_cfg_init(IS_ENABLED(CONFIG_WDT_CTLR)); if (ret) { return ret; diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.h b/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.h index f77a3a03f4e..9611a26d9df 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/bt_mgmt.h @@ -9,6 +9,7 @@ #include #include +#include #define LE_AUDIO_EXTENDED_ADV_NAME \ BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_NAME, \ @@ -19,6 +20,11 @@ BT_LE_ADV_OPT_USE_NAME, \ CONFIG_BLE_ACL_EXT_ADV_INT_MIN, CONFIG_BLE_ACL_EXT_ADV_INT_MAX, NULL) +#define LE_AUDIO_EXTENDED_ADV_CONN_NAME_FILTER \ + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CONNECTABLE | \ + BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_FILTER_CONN, \ + CONFIG_BLE_ACL_EXT_ADV_INT_MIN, CONFIG_BLE_ACL_EXT_ADV_INT_MAX, NULL) + #define LE_AUDIO_PERIODIC_ADV \ BT_LE_PER_ADV_PARAM(CONFIG_BLE_ACL_PER_ADV_INT_MIN, CONFIG_BLE_ACL_PER_ADV_INT_MAX, \ BT_LE_PER_ADV_OPT_NONE) @@ -47,6 +53,8 @@ enum bt_mgmt_scan_type { BT_MGMT_SCAN_TYPE_BROADCAST = 2, }; +#define BRDCAST_ID_NOT_USED (BT_AUDIO_BROADCAST_ID_MAX + 1) + /** * @brief Start scanning for advertisements. * @@ -59,6 +67,10 @@ enum bt_mgmt_scan_type { * device name or broadcast name. Can be max * BLE_SEARCH_NAME_MAX_LEN long; everything beyond that value * will be cropped. Can be NULL. Shall be '\0' terminated. + * @param[in] brdcast_id Broadcast ID to search for. Only valid if @p type is + * BT_MGMT_SCAN_TYPE_BROADCAST. If both @p name and @p brdcast_id are + * provided, then brdcast_id will be used. + * Set to BRDCAST_ID_NOT_USED if not in use. * * @note To restart scanning, call this function with all 0s and NULL, except for @p type. * The same scanning parameters as when bt_mgmt_scan_start was last called will then @@ -67,7 +79,18 @@ enum bt_mgmt_scan_type { * @return 0 if success, error otherwise. */ int bt_mgmt_scan_start(uint16_t scan_intvl, uint16_t scan_win, enum bt_mgmt_scan_type type, - char const *const name); + char const *const name, uint32_t brdcast_id); + +/** + * @brief Add manufacturer ID UUID to the advertisement packet. + * + * @param[out] uuid_buf Buffer being populated with UUIDs. + * @param[in] company_id 16 bit UUID specific to the company. + * + * @return 0 for success, error otherwise. + */ +int bt_mgmt_manufacturer_uuid_populate(struct net_buf_simple *uuid_buf, uint16_t company_id); + /** * @brief Create and start advertising for ACL connection. * diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig index d9582da718e..987ca4b0d7a 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig @@ -4,8 +4,6 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -rsource "Kconfig.defaults" - menu "Controller config" #----------------------------------------------------------------------------# diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig.defaults b/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig.defaults deleted file mode 100644 index 1a41d1511bd..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/Kconfig.defaults +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Bluetooth controller type -if BT_LL_ACS_NRF53 - -# Not supported on LE Audio Controller Subsystem for nRF53 -config BT_ATT_ENFORCE_FLOW - default n - -# Disable Zephyr HCI Vendor-Specific extensions -config BT_HCI_VS_EXT - default n - -# HCI ACL flow control is not supported on BT_LL_ACS_NRF53 -config BT_HCI_ACL_FLOW_CONTROL - default n - -endif # BT_LL_ACS_NRF53 diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/bt_mgmt_ctlr_cfg.c b/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/bt_mgmt_ctlr_cfg.c index b6c7fee1e9b..9679277a6fd 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/bt_mgmt_ctlr_cfg.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/controller_config/bt_mgmt_ctlr_cfg.c @@ -12,118 +12,32 @@ #include #include "macros_common.h" -#if (CONFIG_BT_LL_ACS_NRF53) -#include "ble_hci_vsc.h" -#endif /* (CONFIG_BT_LL_ACS_NRF53) */ #include LOG_MODULE_REGISTER(bt_mgmt_ctlr_cfg, CONFIG_BT_MGMT_CTLR_CFG_LOG_LEVEL); -#define COMPANY_ID_NORDIC 0x0059 -#define COMPANY_ID_PACKETCRAFT 0x07E8 +#define COMPANY_ID_NORDIC 0x0059 -#define WDT_TIMEOUT_MS 1200 -#define CTLR_POLL_INTERVAL_MS (WDT_TIMEOUT_MS - 200) +#define WDT_TIMEOUT_MS 1500 +#define CTLR_POLL_INTERVAL_MS (WDT_TIMEOUT_MS - 500) static struct k_work work_ctlr_poll; -static void ctlr_poll_timer_handler(struct k_timer *timer_id); -static int wdt_ch_id; - -K_TIMER_DEFINE(ctlr_poll_timer, ctlr_poll_timer_handler, NULL); - -static int bt_ll_acs_nrf53_cfg(void) -{ -#if (CONFIG_BT_LL_ACS_NRF53) - int ret; - /* Enable notification of lost ISO packets */ - ret = ble_hci_vsc_op_flag_set(BLE_HCI_VSC_OP_ISO_LOST_NOTIFY, 1); - if (ret) { - return ret; - } - -#if (CONFIG_NRF_21540_ACTIVE) - /* Indexes for the pins gotten from nrf21540ek_fwd.overlay */ - uint8_t tx_pin = NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_PATH(nrf_gpio_forwarder, nrf21540_gpio_if), - gpios, 0); - uint8_t rx_pin = NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_PATH(nrf_gpio_forwarder, nrf21540_gpio_if), - gpios, 1); - uint8_t pdn_pin = NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_PATH(nrf_gpio_forwarder, nrf21540_gpio_if), - gpios, 2); - uint8_t ant_pin = NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_PATH(nrf_gpio_forwarder, nrf21540_gpio_if), - gpios, 3); - uint8_t mode_pin = NRF_DT_GPIOS_TO_PSEL_BY_IDX( - DT_PATH(nrf_gpio_forwarder, nrf21540_gpio_if), gpios, 4); - - struct ble_hci_vs_cp_nrf21540_pins nrf21540_pins = { - .mode = mode_pin, - .txen = tx_pin, - .rxen = rx_pin, - .antsel = ant_pin, - .pdn = pdn_pin, - /* Set CS pin to ffff since we are not using the SPI */ - .csn = 0xffff}; - - ret = ble_hci_vsc_nrf21540_pins_set(&nrf21540_pins); - if (ret) { - return ret; - } - - ret = ble_hci_vsc_radio_high_pwr_mode_set( - MAX(CONFIG_NRF_21540_MAIN_DBM, CONFIG_NRF_21540_PRI_ADV_DBM)); - if (ret) { - return ret; - } - ret = ble_hci_vsc_adv_tx_pwr_set(CONFIG_NRF_21540_MAIN_DBM); - if (ret) { - return ret; - } +#define CTLR_POLL_WORK_STACK_SIZE 1024 - LOG_DBG("TX power set to %d", CONFIG_NRF_21540_MAIN_DBM); +K_THREAD_STACK_DEFINE(ctlr_poll_stack_area, CTLR_POLL_WORK_STACK_SIZE); - ret = ble_hci_vsc_pri_adv_chan_max_tx_pwr_set(CONFIG_NRF_21540_PRI_ADV_DBM); - if (ret) { - return ret; - } +struct k_work_q ctrl_poll_work_q; - LOG_DBG("Primary advertising TX power set to %d", CONFIG_NRF_21540_PRI_ADV_DBM); -#else - ret = ble_hci_vsc_adv_tx_pwr_set(CONFIG_BLE_ADV_TX_POWER_DBM); - if (ret) { - return ret; - } +struct k_work_queue_config ctrl_poll_work_q_config = { + .name = "ctlr_poll", + .no_yield = false, +}; - LOG_DBG("TX power set to %d", CONFIG_BLE_ADV_TX_POWER_DBM); - - /* Disabled by default, only used if another TX power for primary adv channels is needed */ - ret = ble_hci_vsc_pri_adv_chan_max_tx_pwr_set(BLE_HCI_VSC_PRI_EXT_ADV_MAX_TX_PWR_DISABLE); - if (ret) { - return ret; - } - -#endif /*CONFIG_NRF_21540_ACTIVE*/ - - /* Map controller LEDs*/ - - ret = ble_hci_vsc_led_pin_map(PAL_LED_ID_CPU_ACTIVE, - DT_GPIO_FLAGS_BY_IDX(DT_NODELABEL(rgb2_green), gpios, 0), - DT_GPIO_PIN_BY_IDX(DT_NODELABEL(rgb2_green), gpios, 0)); - if (ret) { - return ret; - } - - ret = ble_hci_vsc_led_pin_map(PAL_LED_ID_ERROR, - DT_GPIO_FLAGS_BY_IDX(DT_NODELABEL(rgb2_red), gpios, 0), - DT_GPIO_PIN_BY_IDX(DT_NODELABEL(rgb2_red), gpios, 0)); - if (ret) { - return ret; - } +static void ctlr_poll_timer_handler(struct k_timer *timer_id); +static int wdt_ch_id; - return 0; -#else - return -ENODEV; -#endif /* CONFIG_BT_LL_ACS_NRF53*/ -} +K_TIMER_DEFINE(ctlr_poll_timer, ctlr_poll_timer_handler, NULL); static void work_ctlr_poll_handler(struct k_work *work) { @@ -139,12 +53,17 @@ static void work_ctlr_poll_handler(struct k_work *work) static void ctlr_poll_timer_handler(struct k_timer *timer_id) { - k_work_submit(&work_ctlr_poll); + int ret; + + ret = k_work_submit_to_queue(&ctrl_poll_work_q, &work_ctlr_poll); + if (ret < 0) { + LOG_ERR("Work q submit failed: %d", ret); + } } static void wdt_timeout_cb(int channel_id, void *user_data) { - ERR_CHK_MSG(-ETIMEDOUT, "Controller not responsive"); + ERR_CHK_MSG(-ETIMEDOUT, "No response from IPC or controller"); } int bt_mgmt_ctlr_cfg_manufacturer_get(bool print_version, uint16_t *manufacturer) @@ -160,12 +79,7 @@ int bt_mgmt_ctlr_cfg_manufacturer_get(bool print_version, uint16_t *manufacturer struct bt_hci_rp_read_local_version_info *rp = (void *)rsp->data; if (print_version) { - if (rp->manufacturer == COMPANY_ID_PACKETCRAFT) { - /* NOTE: The string below is used by the Nordic CI system */ - LOG_INF("Controller: LL_ACS_NRF53: Version %s (0x%02x), Revision %d", - bt_hci_get_ver_str(rp->hci_version), rp->hci_version, - rp->hci_revision); - } else if (rp->manufacturer == COMPANY_ID_NORDIC) { + if (rp->manufacturer == COMPANY_ID_NORDIC) { /* NOTE: The string below is used by the Nordic CI system */ LOG_INF("Controller: SoftDevice: Version %s (0x%02x), Revision %d", bt_hci_get_ver_str(rp->hci_version), rp->hci_version, @@ -193,18 +107,6 @@ int bt_mgmt_ctlr_cfg_init(bool watchdog_enable) return ret; } - if ((IS_ENABLED(CONFIG_BT_LL_ACS_NRF53) && (manufacturer != COMPANY_ID_PACKETCRAFT)) || - (!IS_ENABLED(CONFIG_BT_LL_ACS_NRF53) && (manufacturer == COMPANY_ID_PACKETCRAFT))) { - LOG_ERR("Controller config on APP and controller on NET mismatch."); - } - - if (IS_ENABLED(CONFIG_BT_LL_ACS_NRF53) && (manufacturer == COMPANY_ID_PACKETCRAFT)) { - ret = bt_ll_acs_nrf53_cfg(); - if (ret) { - return ret; - } - } - if (watchdog_enable) { ret = task_wdt_init(NULL); if (ret != 0) { @@ -216,6 +118,12 @@ int bt_mgmt_ctlr_cfg_init(bool watchdog_enable) if (wdt_ch_id < 0) { return wdt_ch_id; } + k_work_queue_init(&ctrl_poll_work_q); + + k_work_queue_start(&ctrl_poll_work_q, ctlr_poll_stack_area, + K_THREAD_STACK_SIZEOF(ctlr_poll_stack_area), + K_PRIO_PREEMPT(CONFIG_CTLR_POLL_WORK_Q_PRIO), + &ctrl_poll_work_q_config); k_work_init(&work_ctlr_poll, work_ctlr_poll_handler); k_timer_start(&ctlr_poll_timer, K_MSEC(CTLR_POLL_INTERVAL_MS), diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan.c b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan.c index 6aef4ec9e34..5466c1b0898 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan.c @@ -7,6 +7,7 @@ #include "bt_mgmt.h" #include +#include #include "bt_mgmt_scan_for_broadcast_internal.h" #include "bt_mgmt_scan_for_conn_internal.h" @@ -18,23 +19,20 @@ static char srch_name[BLE_SEARCH_NAME_MAX_LEN]; static void addr_print(void) { - int ret; char addr_str[BT_ADDR_LE_STR_LEN]; static struct bt_le_oob _oob = {.addr = 0}; - /* This call will create a new RPA if CONFIG_BT_PRIVACY is enabled */ - ret = bt_le_oob_get_local(BT_ID_DEFAULT, &_oob); - if (ret) { - LOG_ERR("bt_le_oob_get_local failed"); - return; - } + /* NOTE: We are using an internal struct here to get the address without forcing the + * RPA to time out, should be changed once k_forever bug (DRGN-21459) has been fixed + */ + bt_addr_le_copy(&_oob.addr, &bt_dev.random_addr); (void)bt_addr_le_to_str(&_oob.addr, addr_str, BT_ADDR_LE_STR_LEN); LOG_INF("Local addr: %s. May time out. Updates not printed", addr_str); } int bt_mgmt_scan_start(uint16_t scan_intvl, uint16_t scan_win, enum bt_mgmt_scan_type type, - char const *const name) + char const *const name, uint32_t brdcast_id) { int ret; @@ -65,7 +63,7 @@ int bt_mgmt_scan_start(uint16_t scan_intvl, uint16_t scan_win, enum bt_mgmt_scan ret = bt_mgmt_scan_for_conn_start(scan_param, srch_name); } else if (type == BT_MGMT_SCAN_TYPE_BROADCAST && IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK)) { - ret = bt_mgmt_scan_for_broadcast_start(scan_param, srch_name); + ret = bt_mgmt_scan_for_broadcast_start(scan_param, srch_name, brdcast_id); } else { LOG_WRN("Invalid scan type: %d, scan not started", type); return -EINVAL; @@ -75,10 +73,6 @@ int bt_mgmt_scan_start(uint16_t scan_intvl, uint16_t scan_win, enum bt_mgmt_scan return ret; } - /* As the scanning is started before addr_print, and due to host API limitations, - * this call will create a new RPA if CONFIG_BT_PRIVACY is enabled: - * There is a possibility that a device may connect using the previous RPA. - */ addr_print(); /* NOTE: The string below is used by the Nordic CI system */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast.c b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast.c index 3420fc14bc5..1440c322d63 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "bt_mgmt.h" #include "macros_common.h" @@ -34,14 +35,16 @@ struct bt_le_scan_cb scan_callback; static bool scan_cb_registered; static bool sync_cb_registered; static char const *srch_name; +static uint32_t srch_brdcast_id = BRDCAST_ID_NOT_USED; static struct bt_le_per_adv_sync *pa_sync; -static uint32_t broadcaster_broadcast_id; struct broadcast_source { char name[BLE_SEARCH_NAME_MAX_LEN]; - uint32_t broadcast_id; + uint32_t id; }; +static struct broadcast_source brcast_src_info; + static void scan_restart_worker(struct k_work *work) { int ret; @@ -57,7 +60,7 @@ static void scan_restart_worker(struct k_work *work) LOG_WRN("Failed to delete pending PA sync: %d", ret); } - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL); + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_BROADCAST, NULL, BRDCAST_ID_NOT_USED); if (ret) { LOG_WRN("Failed to restart scanning for broadcast: %d", ret); } @@ -90,7 +93,8 @@ static uint16_t interval_to_sync_timeout(uint16_t interval) return timeout; } -static void periodic_adv_sync(const struct bt_le_scan_recv_info *info, uint32_t broadcast_id) +static void periodic_adv_sync(const struct bt_le_scan_recv_info *info, + struct broadcast_source source) { int ret; struct bt_le_per_adv_sync_param param; @@ -104,8 +108,6 @@ static void periodic_adv_sync(const struct bt_le_scan_recv_info *info, uint32_t param.skip = PA_SYNC_SKIP; param.timeout = interval_to_sync_timeout(info->interval); - broadcaster_broadcast_id = broadcast_id; - /* Set timeout to same value as PA sync timeout in ms */ k_timer_start(&pa_sync_timer, K_MSEC(param.timeout * 10), K_NO_WAIT); @@ -118,6 +120,7 @@ static void periodic_adv_sync(const struct bt_le_scan_recv_info *info, uint32_t } return; } + brcast_src_info = source; } /** @@ -162,7 +165,7 @@ static bool scan_check_broadcast_source(struct bt_data *data, void *user_data) return true; } - source->broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + source->id = sys_get_le24(data->data + BT_UUID_SIZE_16); return true; } @@ -175,7 +178,7 @@ static bool scan_check_broadcast_source(struct bt_data *data, void *user_data) */ static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) { - struct broadcast_source source = {.broadcast_id = INVALID_BROADCAST_ID}; + struct broadcast_source source = {.id = INVALID_BROADCAST_ID}; /* We are only interested in non-connectable periodic advertisers */ if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) || info->interval == 0) { @@ -184,12 +187,21 @@ static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf bt_data_parse(ad, scan_check_broadcast_source, (void *)&source); - if (source.broadcast_id != INVALID_BROADCAST_ID) { - if (strncmp(source.name, srch_name, BLE_SEARCH_NAME_MAX_LEN) == 0) { - LOG_INF("Broadcast source %s found, id: 0x%06x", source.name, - source.broadcast_id); - periodic_adv_sync(info, source.broadcast_id); + if (source.id != INVALID_BROADCAST_ID) { + if (srch_brdcast_id < BRDCAST_ID_NOT_USED) { + /* Valid srch_brdcast_id supplied */ + if (source.id != srch_brdcast_id) { + /* Broadcaster does not match src_brdcast_id */ + return; + } + + } else if (strncmp(source.name, srch_name, BLE_SEARCH_NAME_MAX_LEN) != 0) { + /* Broadcaster does not match src_name */ + return; } + + LOG_DBG("Broadcast source %s found, id: 0x%06x", source.name, source.id); + periodic_adv_sync(info, source); } } @@ -204,7 +216,10 @@ static void pa_synced_cb(struct bt_le_per_adv_sync *sync, return; } - LOG_DBG("PA synced"); + char addr_str[BT_ADDR_LE_STR_LEN]; + (void)bt_addr_le_to_str(&sync->addr, addr_str, BT_ADDR_LE_STR_LEN); + LOG_INF("PA synced to name: %s, id: 0x%06x, addr: %s", brcast_src_info.name, + brcast_src_info.id, addr_str); k_timer_stop(&pa_sync_timer); @@ -215,7 +230,7 @@ static void pa_synced_cb(struct bt_le_per_adv_sync *sync, msg.event = BT_MGMT_PA_SYNCED; msg.pa_sync = sync; - msg.broadcast_id = broadcaster_broadcast_id; + msg.broadcast_id = brcast_src_info.id; ret = zbus_chan_pub(&bt_mgmt_chan, &msg, K_NO_WAIT); ERR_CHK(ret); @@ -242,7 +257,8 @@ static struct bt_le_per_adv_sync_cb sync_callbacks = { .term = pa_sync_terminated_cb, }; -int bt_mgmt_scan_for_broadcast_start(struct bt_le_scan_param *scan_param, char const *const name) +int bt_mgmt_scan_for_broadcast_start(struct bt_le_scan_param *scan_param, char const *const name, + uint32_t brdcast_id) { int ret; @@ -270,6 +286,9 @@ int bt_mgmt_scan_for_broadcast_start(struct bt_le_scan_param *scan_param, char c } srch_name = name; + if (brdcast_id != BRDCAST_ID_NOT_USED) { + srch_brdcast_id = brdcast_id; + } ret = bt_le_scan_start(scan_param, NULL); if (ret) { diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast_internal.h b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast_internal.h index 0db7b9a81bb..f4c89eacb2f 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast_internal.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_broadcast_internal.h @@ -14,9 +14,11 @@ * * @param[in] scan_param Pointer to the struct containing parameters to use. * @param[in] name Broadcast name to search for. + * @param[in] brdcast_id Broadcast ID to search for. * * @return 0 if success, error otherwise. */ -int bt_mgmt_scan_for_broadcast_start(struct bt_le_scan_param *scan_param, char const *const name); +int bt_mgmt_scan_for_broadcast_start(struct bt_le_scan_param *scan_param, char const *const name, + uint32_t brdcast_id); #endif /* _BT_MGMT_SCAN_FOR_BROADCAST_INTERNAL_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_conn.c b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_conn.c index 02b1eda777d..4216d4c1086 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_conn.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_management/scanning/bt_mgmt_scan_for_conn.c @@ -43,6 +43,22 @@ static void bond_connect(const struct bt_bond_info *info, void *user_data) if (!bt_addr_le_cmp(&info->addr, adv_addr)) { LOG_DBG("Found bonded device"); + /* Check if the device is still connected due to waiting for ACL timeout */ + struct bt_conn *bonded_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &info->addr); + struct bt_conn_info info; + + if (bonded_conn != NULL) { + ret = bt_conn_get_info(bonded_conn, &info); + if (ret == 0 && info.state == BT_CONN_STATE_CONNECTED) { + LOG_DBG("Trying to connect to an already connected conn"); + bt_conn_unref(bonded_conn); + return; + } + + /* Unref is needed due to bt_conn_lookup */ + bt_conn_unref(bonded_conn); + } + bt_le_scan_cb_unregister(&scan_callback); cb_registered = false; @@ -60,7 +76,8 @@ static void bond_connect(const struct bt_bond_info *info, void *user_data) if (ret) { LOG_WRN("Create ACL connection failed: %d", ret); - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL); + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL, + BRDCAST_ID_NOT_USED); if (ret) { LOG_ERR("Failed to restart scanning: %d", ret); } @@ -85,11 +102,26 @@ static bool device_name_check(struct bt_data *data, void *user_data) char addr_string[BT_ADDR_LE_STR_LEN]; /* We only care about LTVs with name */ - if (data->type == BT_DATA_NAME_COMPLETE) { + if (data->type == BT_DATA_NAME_COMPLETE || data->type == BT_DATA_NAME_SHORTENED) { size_t srch_name_size = strlen(srch_name); if ((data->data_len == srch_name_size) && (strncmp(srch_name, data->data, srch_name_size) == 0)) { + /* Check if the device is still connected due to waiting for ACL timeout */ + struct bt_conn_info info; + struct bt_conn *existing_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); + + if (existing_conn != NULL) { + ret = bt_conn_get_info(existing_conn, &info); + if (ret == 0 && info.state == BT_CONN_STATE_CONNECTED) { + LOG_DBG("Trying to connect to an already connected conn"); + bt_conn_unref(existing_conn); + return false; + } + + /* Unref is needed due to bt_conn_lookup */ + bt_conn_unref(existing_conn); + } LOG_DBG("Device found: %s", srch_name); bt_le_scan_cb_unregister(&scan_callback); @@ -107,9 +139,10 @@ static bool device_name_check(struct bt_data *data, void *user_data) ret = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, CONNECTION_PARAMETERS, &conn); if (ret) { - LOG_ERR("Could not init connection"); + LOG_ERR("Could not init connection: %d", ret); - ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL); + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL, + BRDCAST_ID_NOT_USED); if (ret) { LOG_ERR("Failed to restart scanning: %d", ret); } @@ -149,6 +182,11 @@ static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf /* Note: May lead to connection creation */ if (bonded_num < CONFIG_BT_MAX_PAIRED) { bt_data_parse(ad, device_name_check, (void *)info->addr); + } else { + /* All bonded slots are taken, so we will only + * accept previously bonded devices + */ + bt_foreach_bond(BT_ID_DEFAULT, bond_connect, (void *)info->addr); } break; default: @@ -169,7 +207,7 @@ int bt_mgmt_scan_for_conn_start(struct bt_le_scan_param *scan_param, char const } else { /* Already scanning, stop current scan to update param in case it has changed */ ret = bt_le_scan_stop(); - if (ret) { + if (ret && ret != -EALREADY) { LOG_ERR("Failed to stop scan: %d", ret); return ret; } diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/bt_renderer/CMakeLists.txt deleted file mode 100644 index deb967c8e01..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -zephyr_library_include_directories( - volume -) - -target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/bt_rend.c) - -if (CONFIG_BT_VCP_VOL_CTLR OR CONFIG_BT_VCP_VOL_REND) -target_sources(app PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/volume/bt_rend_vol.c) -endif() diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_renderer/Kconfig deleted file mode 100644 index 4eb3dfffb1c..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -menu "BT renderer" - -rsource "volume/Kconfig" - -#----------------------------------------------------------------------------# -menu "Log level" - -module = BT_REND -module-str = bt-rend -source "subsys/logging/Kconfig.template.log_config" - -endmenu # Log level -endmenu # BT renderer diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.c b/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.c deleted file mode 100644 index 5820bf872cd..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "bt_rend.h" - -#include -#include -#include - -#include "bt_rend_vol_internal.h" -#include "nrf5340_audio_common.h" - -#include -LOG_MODULE_REGISTER(bt_rend, CONFIG_BT_REND_LOG_LEVEL); - -ZBUS_CHAN_DEFINE(volume_chan, struct volume_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, - ZBUS_MSG_INIT(0)); - -int bt_rend_volume_up(void) -{ - int ret; - struct volume_msg msg; - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR) || IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - ret = bt_rend_vol_up(); - return ret; - } - - msg.event = VOLUME_UP; - - ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); - return ret; -} - -int bt_rend_volume_down(void) -{ - int ret; - struct volume_msg msg; - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR) || IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - ret = bt_rend_vol_down(); - return ret; - } - - msg.event = VOLUME_DOWN; - - ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); - return ret; -} - -int bt_rend_volume_set(uint8_t volume, bool from_vcp) -{ - int ret; - struct volume_msg msg; - - if ((IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR) || IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) && - !from_vcp) { - ret = bt_rend_vol_set(volume); - return ret; - } - - msg.event = VOLUME_SET; - msg.volume = volume; - - ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); - return ret; -} - -int bt_rend_volume_mute(bool from_vcp) -{ - int ret; - struct volume_msg msg; - - if ((IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR) || IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) && - !from_vcp) { - ret = bt_rend_vol_mute(); - return ret; - } - - msg.event = VOLUME_MUTE; - - ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); - return ret; -} - -int bt_rend_volume_unmute(void) -{ - int ret; - struct volume_msg msg; - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR) || IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - ret = bt_rend_vol_unmute(); - return ret; - } - - msg.event = VOLUME_UNMUTE; - - ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); - return ret; -} - -int bt_rend_discover(struct bt_conn *conn) -{ - int ret; - - /* Only do a VCS discover if we are volume controller */ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - ret = bt_rend_vol_discover(conn); - if (ret) { - LOG_WRN("Failed to discover VCS: %d", ret); - return ret; - } - } - - return 0; -} - -int bt_rend_uuid_populate(struct net_buf_simple *uuid_buf) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - if (net_buf_simple_tailroom(uuid_buf) >= BT_UUID_SIZE_16) { - net_buf_simple_add_le16(uuid_buf, BT_UUID_VCS_VAL); - } else { - return -ENOMEM; - } - } - - return 0; -} - -int bt_rend_init(void) -{ - int ret; - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - ret = bt_rend_vol_ctlr_init(); - - if (ret) { - LOG_WRN("Failed to initialize VCS controller: %d", ret); - return ret; - } - } - - if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - ret = bt_rend_vol_rend_init(); - - if (ret) { - LOG_WRN("Failed to initialize VCS renderer: %d", ret); - return ret; - } - } - - return 0; -} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.h b/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.h deleted file mode 100644 index a0fd5d51b5a..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/bt_rend.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _BT_REND_H_ -#define _BT_REND_H_ - -#include - -/** - * @brief Adjust volume up by one step. - * - * @return 0 if success, error otherwise. - */ -int bt_rend_volume_up(void); - -/** - * @brief Adjust volume down by one step. - * - * @return 0 if success, error otherwise. - */ -int bt_rend_volume_down(void); - -/** - * @brief Set the volume to the given @p volume value. - * - * @param[in] volume Value to set the volume to (0-255). - * @param[in] from_vcp Describe if the function was called from a service - * or from somewhere else (buttons, shell, etc). - * - * @return 0 if success, error otherwise. - */ -int bt_rend_volume_set(uint8_t volume, bool from_vcp); - -/** - * @brief Mute the volume. - * - * @param[in] from_vcp Describe if the function was called from a service - * or from somewhere else (buttons, shell, etc). - * - * @return 0 if success, error otherwise. - */ -int bt_rend_volume_mute(bool from_vcp); - -/** - * @brief Unmute the volume. - * - * @return 0 if success, error otherwise. - */ -int bt_rend_volume_unmute(void); - -/** - * @brief Discover the rendering services. - * - * @param[in] conn Pointer to the connection on which to do the discovery. - * - * @return 0 if success, error otherwise. - */ -int bt_rend_discover(struct bt_conn *conn); - -/** - * @brief Put the UUIDs from this module into the buffer. - * - * @note This partial data is used to build a complete extended advertising packet. - * - * @param[out] uuid_buf Buffer being populated with UUIDs. - * - * @return 0 for success, error otherwise. - */ -int bt_rend_uuid_populate(struct net_buf_simple *uuid_buf); - -/** - * @brief Initialize the rendering services or profiles, or both. - * - * @return 0 if success, error otherwise. - */ -int bt_rend_init(void); - -#endif /* _BT_REND_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/Kconfig deleted file mode 100644 index 2cc2f7de218..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -menu "Volume" - -config BT_AUDIO_VOL_DEFAULT - int "Default volume" - range 0 255 - default 195 - help - The default volume when starting a volume control renderer. - -config BT_AUDIO_VOL_STEP_SIZE - int "Volume adjust step size" - range 6 32 - default 16 - -#----------------------------------------------------------------------------# -menu "Log level" - -module = BT_REND_VOL -module-str = bt-rend-vol -source "subsys/logging/Kconfig.template.log_config" - -endmenu # Log level -endmenu # Volume diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol.c b/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol.c deleted file mode 100644 index 40d0d37e1fb..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "bt_rend_vol_internal.h" - -#include -#include -#include -#include - -#include "macros_common.h" -#include "bt_rend.h" - -#include -LOG_MODULE_REGISTER(bt_rend_vol, CONFIG_BT_REND_VOL_LOG_LEVEL); - -static struct bt_vcp_vol_ctlr *vcs_client_peer[CONFIG_BT_MAX_CONN]; - -/** - * @brief Get the index of the first available vcs_client_peer. - * - * @retval Index if success. - * @retval -ENOMEM if no available indexes. - */ -static int vcs_client_peer_index_free_get(void) -{ - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] == NULL) { - return i; - } - } - - LOG_WRN("No more indexes for VCS peer clients"); - - return -ENOMEM; -} - -/** - * @brief Check if the given @p conn has a vcs_client_peer pointer. - * - * @param[in] conn The connection pointer to be checked. - * - * @retval True if vcs_client_peer exists. - * @retval False otherwise. - */ -static bool vcs_client_peer_exists(struct bt_conn *conn) -{ - int ret; - - struct bt_conn *result_conn = NULL; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - ret = bt_vcp_vol_ctlr_conn_get(vcs_client_peer[i], &result_conn); - - if (!ret && conn == result_conn) { - return true; - } - - if (ret == -ENOTCONN) { - /* VCS client no longer connected, free the index */ - vcs_client_peer[i] = NULL; - return false; - } - } - - return false; -} - -/** - * @brief Callback handler for the volume state. - * - * @note This callback handler will be triggered if volume state has changed, - * or the playback was muted or unmuted. - */ -static void vcs_state_ctlr_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t volume, - uint8_t mute) -{ - int ret; - - if (err) { - LOG_ERR("VCS state callback error: %d", err); - return; - } - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs == vcs_client_peer[i]) { - LOG_DBG("VCS state from remote device %d:", i); - continue; - } - - LOG_DBG("Sync with other devices %d", i); - - if (vcs_client_peer[i] == NULL) { - /* Skip */ - continue; - } - - ret = bt_vcp_vol_ctlr_set_vol(vcs_client_peer[i], volume); - if (ret) { - LOG_DBG("Failed to sync volume to remote device %d, err = " - "%d", - i, ret); - } - } -} - -/** - * @brief Callback handler for the VCS controller flags. - * - * @note This callback handler will be triggered if VCS flags changed. - */ -static void vcs_flags_ctlr_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t flags) -{ - if (err) { - LOG_ERR("VCS flag callback error: %d", err); - } else { - LOG_DBG("Volume flags = 0x%01X", flags); - } -} - -/** - * @brief Callback handler for the volume state. - * - * @note This callback handler will be triggered if volume state has changed, - * or the playback was muted or unmuted from the volume_controller. - */ -static void vcs_state_rend_cb_handler(int err, uint8_t volume, uint8_t mute) -{ - int ret; - - if (err) { - LOG_ERR("VCS state callback error: %d", err); - return; - } - LOG_INF("Volume = %d, mute state = %d", volume, mute); - - /* Send to bt_rend */ - ret = bt_rend_volume_set(volume, true); - if (ret) { - LOG_WRN("Failed to set volume"); - } - - if (mute) { - ret = bt_rend_volume_mute(true); - if (ret) { - LOG_WRN("Error muting volume"); - } - } -} - -/** - * @brief Callback handler for the changed VCS renderer flags. - * - * @note This callback handler will be triggered if the VCS flags has changed. - */ -static void vcs_flags_rend_cb_handler(int err, uint8_t flags) -{ - if (err) { - LOG_ERR("VCS flag callback error: %d", err); - } else { - LOG_DBG("Volume flags = 0x%01X", flags); - } -} - -/** - * @brief Callback handler for the finished VCS discovery. - * - * @note This callback handler will be triggered when the VCS discovery has finished. - */ -static void vcs_discover_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t vocs_count, - uint8_t aics_count) -{ - if (err) { - LOG_WRN("VCS discover finished callback error: %d", err); - } else { - LOG_INF("VCS discover finished"); - } -} - -int bt_rend_vol_set(uint8_t volume) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - int ret; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] != NULL) { - ret = bt_vcp_vol_ctlr_set_vol(vcs_client_peer[i], volume); - if (ret) { - LOG_WRN("Failed to set volume for remote channel %d, ret = " - "%d", - i, ret); - } - } - } - - return 0; - } else if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - return bt_vcp_vol_rend_set_vol(volume); - } - - LOG_WRN("VCP not enabled"); - return -EIO; -} - -int bt_rend_vol_up(void) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - int ret; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] != NULL) { - ret = bt_vcp_vol_ctlr_unmute_vol_up(vcs_client_peer[i]); - if (ret) { - LOG_WRN("Failed to volume up for remote channel %d, ret = " - "%d", - i, ret); - } - } - } - - return 0; - } else if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - return bt_vcp_vol_rend_unmute_vol_up(); - } - - LOG_WRN("VCP not enabled"); - return -EIO; -} - -int bt_rend_vol_down(void) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - int ret; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] != NULL) { - ret = bt_vcp_vol_ctlr_unmute_vol_down(vcs_client_peer[i]); - if (ret) { - LOG_WRN("Failed to volume down for remote channel %d, ret " - "= %d", - i, ret); - } - } - } - - return 0; - } else if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - return bt_vcp_vol_rend_unmute_vol_down(); - } - - LOG_WRN("VCP not enabled"); - return -EIO; -} - -int bt_rend_vol_mute(void) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - int ret; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] != NULL) { - ret = bt_vcp_vol_ctlr_mute(vcs_client_peer[i]); - if (ret) { - LOG_WRN("Failed to mute for remote channel %d, ret " - "= %d", - i, ret); - } - } - } - - return 0; - } else if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - return bt_vcp_vol_rend_mute(); - } - - LOG_WRN("VCP not enabled"); - return -EIO; -} - -int bt_rend_vol_unmute(void) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - int ret; - - for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { - if (vcs_client_peer[i] != NULL) { - ret = bt_vcp_vol_ctlr_unmute(vcs_client_peer[i]); - if (ret) { - LOG_WRN("Failed to unmute for remote channel %d, " - "ret = %d", - i, ret); - } - } - } - - return 0; - } else if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - return bt_vcp_vol_rend_unmute(); - } - - LOG_WRN("VCP not enabled"); - return -EIO; -} - -int bt_rend_vol_discover(struct bt_conn *conn) -{ - if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - - int ret, index; - - if (vcs_client_peer_exists(conn)) { - return -EAGAIN; - } - - index = vcs_client_peer_index_free_get(); - if (index < 0) { - return index; - } - - ret = bt_vcp_vol_ctlr_discover(conn, &vcs_client_peer[index]); - return ret; - } - - LOG_ERR("VCP volume controller not enabled"); - return -ECANCELED; -} - -int bt_rend_vol_ctlr_init(void) -{ - if (!IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { - LOG_ERR("VCP volume controller not enabled"); - return -ECANCELED; - } - - static struct bt_vcp_vol_ctlr_cb vcs_client_callback; - - vcs_client_callback.discover = vcs_discover_cb_handler; - vcs_client_callback.state = vcs_state_ctlr_cb_handler; - vcs_client_callback.flags = vcs_flags_ctlr_cb_handler; - - return bt_vcp_vol_ctlr_cb_register(&vcs_client_callback); -} - -int bt_rend_vol_rend_init(void) -{ - if (!IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { - LOG_ERR("VCP volume renderer not enabled"); - return -ECANCELED; - } - - int ret; - struct bt_vcp_vol_rend_register_param vcs_param; - static struct bt_vcp_vol_rend_cb vcs_server_callback; - - vcs_server_callback.state = vcs_state_rend_cb_handler; - vcs_server_callback.flags = vcs_flags_rend_cb_handler; - vcs_param.cb = &vcs_server_callback; - vcs_param.mute = BT_VCP_STATE_UNMUTED; - vcs_param.step = CONFIG_BT_AUDIO_VOL_STEP_SIZE; - vcs_param.volume = CONFIG_BT_AUDIO_VOL_DEFAULT; - - ret = bt_vcp_vol_rend_register(&vcs_param); - if (ret) { - return ret; - } - - return 0; -} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol_internal.h b/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol_internal.h deleted file mode 100644 index 123b76eb591..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/bt_renderer/volume/bt_rend_vol_internal.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _BT_REND_VOL_INTERNAL_H_ -#define _BT_REND_VOL_INTERNAL_H_ - -#include - -/** - * @brief Set volume to a specific value. - * - * @param[in] volume The absolute volume to be set. - * - * @retval 0 Volume change success. - * @retval -ENXIO The feature is disabled. - * @retval other Errors from underlying drivers. - */ -int bt_rend_vol_set(uint8_t volume); - -/** - * @brief Turn the volume up by one step. - * - * @retval 0 Volume change success. - * @retval -ENXIO The feature is disabled. - * @retval other Errors from underlying drivers. - */ -int bt_rend_vol_up(void); - -/** - * @brief Turn the volume down by one step. - * - * @retval 0 Volume change success. - * @retval -ENXIO The feature is disabled. - * @retval other Errors from underlying drivers. - */ -int bt_rend_vol_down(void); - -/** - * @brief Mute the output volume of the device. - * - * @retval 0 Volume change success. - * @retval -ENXIO The feature is disabled. - * @retval other Errors from underlying drivers. - */ -int bt_rend_vol_mute(void); - -/** - * @brief Unmute the output volume of the device. - * - * @retval 0 Volume change success. - * @retval -ENXIO The feature is disabled. - * @retval other Errors from underlying drivers. - */ -int bt_rend_vol_unmute(void); - -/** - * @brief Discover Volume Control Service and included services. - * - * @param[in] conn Pointer to the connection on which to discover the services. - * - * @note This function starts a GATT discovery and sets up handles and - * subscriptions for the VCS and included services. - * Call it once before any other actions related to the VCS. - * - * @return 0 for success, error otherwise. - */ -int bt_rend_vol_discover(struct bt_conn *conn); - -/** - * @brief Initialize the Volume Control Service client. - * - * @return 0 for success, error otherwise. - */ -int bt_rend_vol_ctlr_init(void); - -/** - * @brief Initialize the Volume renderer. - * - * @return 0 for success, error otherwise. - */ -int bt_rend_vol_rend_init(void); - -#endif /* _BT_REND_VOL_INTERNAL_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/CMakeLists.txt new file mode 100644 index 00000000000..b7f7ac8c938 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +zephyr_library_include_directories( + volume +) + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/bt_rendering_and_capture.c) + +if (CONFIG_BT_VCP_VOL_CTLR AND CONFIG_BT_VCP_VOL_REND) + message(FATAL_ERROR "No support for vol controller and renderer on same device") +endif() + +if (CONFIG_BT_VCP_VOL_REND) +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/volume/bt_vol_rend.c) +endif() + +if (CONFIG_BT_VCP_VOL_CTLR) + target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/volume/bt_vol_ctlr.c) +endif() diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/Kconfig new file mode 100644 index 00000000000..e4d526c0d3b --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/Kconfig @@ -0,0 +1,19 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menu "BT renderer" + +rsource "volume/Kconfig" + +#----------------------------------------------------------------------------# +menu "Log level" + +module = BT_RENDERING_AND_CAPTURE +module-str = bt-rendering-and-capture +source "subsys/logging/Kconfig.template.log_config" + +endmenu # Log level +endmenu # BT renderer diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.c b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.c new file mode 100644 index 00000000000..3dd388a5a93 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bt_rendering_and_capture.h" + +#include +#include +#include + +#include "bt_vol_rend_internal.h" +#include "bt_vol_ctlr_internal.h" +#include "nrf5340_audio_common.h" + +#include +LOG_MODULE_REGISTER(bt_r_c, CONFIG_BT_RENDERING_AND_CAPTURE_LOG_LEVEL); + +ZBUS_CHAN_DEFINE(volume_chan, struct volume_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, + ZBUS_MSG_INIT(0)); + +int bt_r_and_c_volume_up(void) +{ + int ret; + struct volume_msg msg; + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { + ret = bt_vol_rend_up(); + return ret; + } + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + ret = bt_vol_ctlr_up(); + return ret; + } + + msg.event = VOLUME_UP; + + ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); + return ret; +} + +int bt_r_and_c_volume_down(void) +{ + int ret; + struct volume_msg msg; + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { + ret = bt_vol_rend_down(); + return ret; + } + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + ret = bt_vol_ctlr_down(); + return ret; + } + + msg.event = VOLUME_DOWN; + + ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); + return ret; +} + +int bt_r_and_c_volume_set(uint8_t volume, bool from_vcp) +{ + int ret; + struct volume_msg msg; + + if ((IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) && !from_vcp) { + ret = bt_vol_rend_set(volume); + return ret; + } + + if ((IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) && !from_vcp) { + ret = bt_vol_ctlr_set(volume); + return ret; + } + + msg.event = VOLUME_SET; + msg.volume = volume; + + ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); + return ret; +} + +int bt_r_and_c_volume_mute(bool from_vcp) +{ + int ret; + struct volume_msg msg; + + if ((IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) && !from_vcp) { + ret = bt_vol_rend_mute(); + return ret; + } + + if ((IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) && !from_vcp) { + ret = bt_vol_ctlr_mute(); + return ret; + } + + msg.event = VOLUME_MUTE; + + ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); + return ret; +} + +int bt_r_and_c_volume_unmute(void) +{ + int ret; + struct volume_msg msg; + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { + ret = bt_vol_rend_unmute(); + return ret; + } + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + ret = bt_vol_ctlr_unmute(); + return ret; + } + + msg.event = VOLUME_UNMUTE; + + ret = zbus_chan_pub(&volume_chan, &msg, K_NO_WAIT); + return ret; +} + +int bt_r_and_c_discover(struct bt_conn *conn) +{ + int ret; + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + ret = bt_vol_ctlr_discover(conn); + if (ret) { + LOG_WRN("Failed to discover VCS: %d", ret); + return ret; + } + } else { + return -ENOTSUP; + } + + return 0; +} + +int bt_r_and_c_uuid_populate(struct net_buf_simple *uuid_buf) +{ + if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { + if (net_buf_simple_tailroom(uuid_buf) >= BT_UUID_SIZE_16) { + net_buf_simple_add_le16(uuid_buf, BT_UUID_VCS_VAL); + } else { + return -ENOMEM; + } + } else { + return -ENOTSUP; + } + + return 0; +} + +int bt_r_and_c_init(void) +{ + int ret; + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_REND)) { + ret = bt_vol_rend_init(); + + if (ret) { + LOG_WRN("Failed to initialize VCS renderer: %d", ret); + return ret; + } + } + + if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR)) { + ret = bt_vol_ctlr_init(); + + if (ret) { + LOG_WRN("Failed to initialize VCS controller: %d", ret); + return ret; + } + } + + return 0; +} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.h b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.h new file mode 100644 index 00000000000..cfefb496efe --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/bt_rendering_and_capture.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _BT_REND_H_ +#define _BT_REND_H_ + +#include + +/** + * @brief Adjust volume up by one step. + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_volume_up(void); + +/** + * @brief Adjust volume down by one step. + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_volume_down(void); + +/** + * @brief Set the volume to the given @p volume value. + * + * @param[in] volume Value to set the volume to (0-255). + * @param[in] from_vcp Describe if the function was called from a service + * or from somewhere else (buttons, shell, etc). + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_volume_set(uint8_t volume, bool from_vcp); + +/** + * @brief Mute the volume. + * + * @param[in] from_vcp Describe if the function was called from a service + * or from somewhere else (buttons, shell, etc). + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_volume_mute(bool from_vcp); + +/** + * @brief Unmute the volume. + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_volume_unmute(void); + +/** + * @brief Discover the rendering services. + * + * @param[in] conn Pointer to the connection on which to do the discovery. + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_discover(struct bt_conn *conn); + +/** + * @brief Put the UUIDs from this module into the buffer. + * + * @note This partial data is used to build a complete extended advertising packet. + * + * @param[out] uuid_buf Buffer being populated with UUIDs. + * + * @return 0 for success, error otherwise. + */ +int bt_r_and_c_uuid_populate(struct net_buf_simple *uuid_buf); + +/** + * @brief Initialize the rendering services or profiles, or both. + * + * @return 0 if success, error otherwise. + */ +int bt_r_and_c_init(void); + +#endif /* _BT_REND_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/Kconfig new file mode 100644 index 00000000000..35306eb08f7 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/Kconfig @@ -0,0 +1,29 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menu "Volume" + +config BT_AUDIO_VOL_DEFAULT + int "Default volume" + range 0 255 + default 195 + help + The default volume when starting a volume control renderer. + +config BT_AUDIO_VOL_STEP_SIZE + int "Volume adjust step size" + range 6 32 + default 16 + +#----------------------------------------------------------------------------# +menu "Log level" + +module = BT_VOL +module-str = bt-vol +source "subsys/logging/Kconfig.template.log_config" + +endmenu # Log level +endmenu # Volume diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr.c b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr.c new file mode 100644 index 00000000000..1024c5ffa3a --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bt_vol_ctlr_internal.h" + +#include +#include +#include +#include + +#include "macros_common.h" +#include "bt_rendering_and_capture.h" + +#include +LOG_MODULE_REGISTER(bt_vol_ctlr, CONFIG_BT_VOL_LOG_LEVEL); + +static struct bt_vcp_vol_ctlr *vcs_client_peer[CONFIG_BT_MAX_CONN]; + +/** + * @brief Get the index of the first available vcs_client_peer. + * + * @retval Index if success. + * @retval -ENOMEM if no available indexes. + */ +static int vcs_client_peer_index_free_get(void) +{ + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] == NULL) { + return i; + } + } + + LOG_WRN("No more indexes for VCS peer clients"); + + return -ENOMEM; +} + +/** + * @brief Check if the given @p conn has a vcs_client_peer pointer. + * + * @param[in] conn The connection pointer to be checked. + * + * @retval True if vcs_client_peer exists. + * @retval False otherwise. + */ +static bool vcs_client_peer_exists(struct bt_conn *conn) +{ + int ret; + + struct bt_conn *result_conn = NULL; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + ret = bt_vcp_vol_ctlr_conn_get(vcs_client_peer[i], &result_conn); + + if (!ret && conn == result_conn) { + return true; + } + + if (ret == -ENOTCONN) { + /* VCS client no longer connected, free the index */ + vcs_client_peer[i] = NULL; + return false; + } + } + + return false; +} + +/** + * @brief Callback handler for the volume state. + * + * @note This callback handler will be triggered if volume state has changed, + * or the playback was muted or unmuted. + */ +static void vcs_state_ctlr_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t volume, + uint8_t mute) +{ + int ret; + + if (err) { + LOG_ERR("VCS state callback error: %d", err); + return; + } + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs == vcs_client_peer[i]) { + LOG_DBG("VCS state from remote device %d:", i); + continue; + } + + LOG_DBG("Sync with other devices %d", i); + + if (vcs_client_peer[i] == NULL) { + /* Skip */ + continue; + } + + ret = bt_vcp_vol_ctlr_set_vol(vcs_client_peer[i], volume); + if (ret) { + LOG_DBG("Failed to sync volume to remote device %d, err = " + "%d", + i, ret); + } + } +} + +/** + * @brief Callback handler for the VCS controller flags. + * + * @note This callback handler will be triggered if VCS flags changed. + */ +static void vcs_flags_ctlr_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t flags) +{ + if (err) { + LOG_ERR("VCS flag callback error: %d", err); + } else { + LOG_DBG("Volume flags = 0x%01X", flags); + } +} + +/** + * @brief Callback handler for the finished VCS discovery. + * + * @note This callback handler will be triggered when the VCS discovery has finished. + */ +static void vcs_discover_cb_handler(struct bt_vcp_vol_ctlr *vcs, int err, uint8_t vocs_count, + uint8_t aics_count) +{ + if (err) { + LOG_WRN("VCS discover finished callback error: %d", err); + } else { + LOG_INF("VCS discover finished"); + } +} + +int bt_vol_ctlr_set(uint8_t volume) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] != NULL) { + ret = bt_vcp_vol_ctlr_set_vol(vcs_client_peer[i], volume); + if (ret) { + LOG_WRN("Failed to set volume for remote channel %d, ret = " + "%d", + i, ret); + } + } + } + + return 0; +} + +int bt_vol_ctlr_up(void) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] != NULL) { + ret = bt_vcp_vol_ctlr_unmute_vol_up(vcs_client_peer[i]); + if (ret) { + LOG_WRN("Failed to volume up for remote channel %d, ret = " + "%d", + i, ret); + } + } + } + + return 0; +} + +int bt_vol_ctlr_down(void) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] != NULL) { + ret = bt_vcp_vol_ctlr_unmute_vol_down(vcs_client_peer[i]); + if (ret) { + LOG_WRN("Failed to volume down for remote channel %d, ret " + "= %d", + i, ret); + } + } + } + + return 0; +} + +int bt_vol_ctlr_mute(void) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] != NULL) { + ret = bt_vcp_vol_ctlr_mute(vcs_client_peer[i]); + if (ret) { + LOG_WRN("Failed to mute for remote channel %d, ret " + "= %d", + i, ret); + } + } + } + + return 0; +} + +int bt_vol_ctlr_unmute(void) +{ + + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcs_client_peer); i++) { + if (vcs_client_peer[i] != NULL) { + ret = bt_vcp_vol_ctlr_unmute(vcs_client_peer[i]); + if (ret) { + LOG_WRN("Failed to unmute for remote channel %d, " + "ret = %d", + i, ret); + } + } + } + + return 0; +} + +int bt_vol_ctlr_discover(struct bt_conn *conn) +{ + + int ret, index; + + if (vcs_client_peer_exists(conn)) { + return -EAGAIN; + } + + index = vcs_client_peer_index_free_get(); + if (index < 0) { + return index; + } + + ret = bt_vcp_vol_ctlr_discover(conn, &vcs_client_peer[index]); + return ret; +} + +int bt_vol_ctlr_init(void) +{ + static struct bt_vcp_vol_ctlr_cb vcs_client_callback; + + vcs_client_callback.discover = vcs_discover_cb_handler; + vcs_client_callback.state = vcs_state_ctlr_cb_handler; + vcs_client_callback.flags = vcs_flags_ctlr_cb_handler; + + return bt_vcp_vol_ctlr_cb_register(&vcs_client_callback); +} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr_internal.h b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr_internal.h new file mode 100644 index 00000000000..cab34789b56 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_ctlr_internal.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _BT_VOL_CTLR_INTERNAL_H_ +#define _BT_VOL_CTLR_INTERNAL_H_ + +#include + +/** + * @brief Set volume to a specific value. + * + * @param[in] volume The absolute volume to be set. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_ctlr_set(uint8_t volume); + +/** + * @brief Turn the volume up by one step. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_ctlr_up(void); + +/** + * @brief Turn the volume down by one step. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_ctlr_down(void); + +/** + * @brief Mute the output volume of the device. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_ctlr_mute(void); + +/** + * @brief Unmute the output volume of the device. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_ctlr_unmute(void); + +/** + * @brief Discover Volume Control Service and included services. + * + * @param[in] conn Pointer to the connection on which to discover the services. + * + * @note This function starts a GATT discovery and sets up handles and + * subscriptions for the VCS and included services. + * Call it once before any other actions related to the VCS. + * + * @return 0 for success, error otherwise. + */ +int bt_vol_ctlr_discover(struct bt_conn *conn); + +/** + * @brief Initialize the Volume Control Service client. + * + * @return 0 for success, error otherwise. + */ +int bt_vol_ctlr_init(void); + +#endif /* _BT_VOL_CTLR_INTERNAL_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend.c b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend.c new file mode 100644 index 00000000000..3954365997e --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bt_vol_rend_internal.h" + +#include +#include +#include +#include + +#include "macros_common.h" +#include "bt_rendering_and_capture.h" + +#include +LOG_MODULE_REGISTER(bt_vol_rend, CONFIG_BT_VOL_LOG_LEVEL); + +/** + * @brief Callback handler for the volume state. + * + * @note This callback handler will be triggered if volume state has changed, + * or the playback was muted or unmuted from the volume_controller. + */ +static void vcs_state_rend_cb_handler(int err, uint8_t volume, uint8_t mute) +{ + int ret; + + if (err) { + LOG_ERR("VCS state callback error: %d", err); + return; + } + LOG_INF("Volume = %d, mute state = %d", volume, mute); + + /* Send to bt_rend */ + ret = bt_r_and_c_volume_set(volume, true); + if (ret) { + LOG_WRN("Failed to set volume"); + } + + if (mute) { + ret = bt_r_and_c_volume_mute(true); + if (ret) { + LOG_WRN("Error muting volume"); + } + } +} + +/** + * @brief Callback handler for the changed VCS renderer flags. + * + * @note This callback handler will be triggered if the VCS flags has changed. + */ +static void vcs_flags_rend_cb_handler(int err, uint8_t flags) +{ + if (err) { + LOG_ERR("VCS flag callback error: %d", err); + } else { + LOG_DBG("Volume flags = 0x%01X", flags); + } +} + +int bt_vol_rend_set(uint8_t volume) +{ + + return bt_vcp_vol_rend_set_vol(volume); +} + +int bt_vol_rend_up(void) +{ + return bt_vcp_vol_rend_unmute_vol_up(); +} + +int bt_vol_rend_down(void) +{ + + return bt_vcp_vol_rend_unmute_vol_down(); +} + +int bt_vol_rend_mute(void) +{ + return bt_vcp_vol_rend_mute(); +} + +int bt_vol_rend_unmute(void) +{ + return bt_vcp_vol_rend_unmute(); +} + +int bt_vol_rend_init(void) +{ + int ret; + struct bt_vcp_vol_rend_register_param vcs_param; + static struct bt_vcp_vol_rend_cb vcs_server_callback; + + vcs_server_callback.state = vcs_state_rend_cb_handler; + vcs_server_callback.flags = vcs_flags_rend_cb_handler; + vcs_param.cb = &vcs_server_callback; + vcs_param.mute = BT_VCP_STATE_UNMUTED; + vcs_param.step = CONFIG_BT_AUDIO_VOL_STEP_SIZE; + vcs_param.volume = CONFIG_BT_AUDIO_VOL_DEFAULT; + + ret = bt_vcp_vol_rend_register(&vcs_param); + if (ret) { + return ret; + } + + return 0; +} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend_internal.h b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend_internal.h new file mode 100644 index 00000000000..cdbd1f81b2d --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_rendering_and_capture/volume/bt_vol_rend_internal.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _BT_VOL_REND_INTERNAL_H_ +#define _BT_VOL_REND_INTERNAL_H_ + +#include +/** + * @brief Set volume to a specific value. + * + * @param[in] volume The absolute volume to be set. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_rend_set(uint8_t volume); + +/** + * @brief Turn the volume up by one step. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_rend_up(void); + +/** + * @brief Turn the volume down by one step. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_rend_down(void); + +/** + * @brief Mute the output volume of the device. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_rend_mute(void); + +/** + * @brief Unmute the output volume of the device. + * + * @retval 0 Volume change success. + * @retval -ENXIO The feature is disabled. + * @retval other Errors from underlying drivers. + */ +int bt_vol_rend_unmute(void); + +/** + * @brief Initialize the Volume renderer. + * + * @return 0 for success, error otherwise. + */ +int bt_vol_rend_init(void); + +#endif /* _BT_VOL_REND_INTERNAL_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/bt_stream/CMakeLists.txt index c1dfe86c538..389ec2d4f46 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/CMakeLists.txt +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/CMakeLists.txt @@ -7,8 +7,14 @@ zephyr_library_include_directories( broadcast unicast + bt_le_audio_tx ) +add_subdirectory(bt_le_audio_tx) + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/le_audio.c) + if (CONFIG_BT_BAP_BROADCAST_SINK) target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/broadcast/broadcast_sink.c) diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig index 316e4200873..34ac2417099 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig @@ -30,13 +30,6 @@ config BT_BAP_BROADCAST_16_2_1 Broadcast mandatory codec capability 16_2_1. 16kHz, 32kbps, 2 retransmits, 10ms transport latency, and 40ms presentation delay. -config BT_BAP_BROADCAST_24_2_1 - bool "24_2_1" - depends on TRANSPORT_BIS - help - Broadcast codec capability 24_2_1. - 24kHz, 48kbps, 2 retransmits, 10ms transport latency, and 40ms presentation delay. - config BT_BAP_BROADCAST_16_2_2 bool "16_2_2" depends on TRANSPORT_BIS @@ -44,12 +37,62 @@ config BT_BAP_BROADCAST_16_2_2 Broadcast mandatory codec capability 16_2_2. 16kHz, 32kbps, 4 retransmits, 60ms transport latency, and 40ms presentation delay. +config BT_BAP_BROADCAST_24_2_1 + bool "24_2_1" + depends on TRANSPORT_BIS + help + Broadcast codec capability 24_2_1. + 24kHz, 48kbps, 2 retransmits, 10ms transport latency, and 40ms presentation delay. + config BT_BAP_BROADCAST_24_2_2 bool "24_2_2" depends on TRANSPORT_BIS help Broadcast codec capability 24_2_2. 24kHz, 48kbps, 4 retransmits, 60ms transport latency, and 40ms presentation delay. + +config BT_BAP_BROADCAST_48_2_1 + bool "48_2_1" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_2_1. + 48kHz, 80kbps, 4 retransmits, 20ms transport latency, and 40ms presentation delay. + +config BT_BAP_BROADCAST_48_2_2 + bool "48_2_2" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_2_2. + 48kHz, 80kbps, 4 retransmits, 65ms transport latency, and 40ms presentation delay. + +config BT_BAP_BROADCAST_48_4_1 + bool "48_4_1" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_4_1. + 48kHz, 96kbps, 4 retransmits, 20ms transport latency, and 40ms presentation delay. + +config BT_BAP_BROADCAST_48_4_2 + bool "48_4_2" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_4_2. + 48kHz, 96kbps, 4 retransmits, 65ms transport latency, and 40ms presentation delay. + + +config BT_BAP_BROADCAST_48_6_1 + bool "48_6_1" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_6_1. + 48kHz, 124kbps, 4 retransmits, 20ms transport latency, and 40ms presentation delay. + +config BT_BAP_BROADCAST_48_6_2 + bool "48_6_2" + depends on TRANSPORT_BIS + help + Broadcast codec capability 48_6_2. + 48kHz, 124kbps, 4 retransmits, 65ms transport latency, and 40ms presentation delay. endchoice config BT_AUDIO_BROADCAST_NAME @@ -104,6 +147,30 @@ config BT_AUDIO_BROADCAST_ID_FIXED Fixed broadcast ID; 3 octets. Will only be used if BT_AUDIO_USE_BROADCAST_ID_RANDOM=n. Only use for debugging. +config BT_AUDIO_BROADCAST_PARENTAL_RATING + hex "Parental rating" + depends on TRANSPORT_BIS + default 0x00 + range 0x00 0x0F + help + Set the parental rating for the broadcast. + BT_AUDIO_PARENTAL_RATING_NO_RATING = 0x00, + BT_AUDIO_PARENTAL_RATING_AGE_ANY = 0x01, + BT_AUDIO_PARENTAL_RATING_AGE_5_OR_ABOVE = 0x02, + BT_AUDIO_PARENTAL_RATING_AGE_6_OR_ABOVE = 0x03, + BT_AUDIO_PARENTAL_RATING_AGE_7_OR_ABOVE = 0x04, + BT_AUDIO_PARENTAL_RATING_AGE_8_OR_ABOVE = 0x05, + BT_AUDIO_PARENTAL_RATING_AGE_9_OR_ABOVE = 0x06, + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE = 0x07, + BT_AUDIO_PARENTAL_RATING_AGE_11_OR_ABOVE = 0x08, + BT_AUDIO_PARENTAL_RATING_AGE_12_OR_ABOVE = 0x09, + BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE = 0x0A, + BT_AUDIO_PARENTAL_RATING_AGE_14_OR_ABOVE = 0x0B, + BT_AUDIO_PARENTAL_RATING_AGE_15_OR_ABOVE = 0x0C, + BT_AUDIO_PARENTAL_RATING_AGE_16_OR_ABOVE = 0x0D, + BT_AUDIO_PARENTAL_RATING_AGE_17_OR_ABOVE = 0x0E, + BT_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE = 0x0F + config BT_AUDIO_BROADCAST_IMMEDIATE_FLAG bool "Immediate rendering flag" depends on TRANSPORT_BIS @@ -125,6 +192,9 @@ config BT_AUDIO_BITRATE_BROADCAST_SRC default 96000 if BT_AUDIO_BROADCAST_CONFIGURABLE default 32000 if BT_BAP_BROADCAST_16_2_1 || BT_BAP_BROADCAST_16_2_2 default 48000 if BT_BAP_BROADCAST_24_2_1 || BT_BAP_BROADCAST_24_2_2 + default 80000 if BT_BAP_BROADCAST_48_2_1 || BT_BAP_BROADCAST_48_2_2 + default 96000 if BT_BAP_BROADCAST_48_4_1 || BT_BAP_BROADCAST_48_4_2 + default 124000 if BT_BAP_BROADCAST_48_6_1 || BT_BAP_BROADCAST_48_6_2 help Bitrate for the broadcast source ISO stream. diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig.defaults b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig.defaults index fef5b71504d..63eccfa46cd 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig.defaults +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/Kconfig.defaults @@ -7,83 +7,5 @@ config BT_BUF_ACL_RX_SIZE default 502 if (AUDIO_DFU > 0) -# HEADSET -if AUDIO_DEV = 1 - -config BT_OBSERVER - default y - -config BT_PERIPHERAL - default y - -config BT_DEVICE_APPEARANCE - # Generic Audio Sink - 0x0840 - default 2112 - -config BT_ISO_SYNC_RECEIVER - default y - -config BT_BAP_BROADCAST_SINK - default y - -config BT_BAP_SCAN_DELEGATOR - default y - -config BT_BAP_BROADCAST_SNK_STREAM_COUNT - default 2 - -config BT_BAP_BROADCAST_SNK_COUNT - default 2 - -config BT_ISO_MAX_CHAN - default 2 - -config BT_ISO_MAX_BIG - default 2 - -config BT_PER_ADV_SYNC_MAX - default 2 - -config BT_SMP - default y - -config BT_PAC_SNK - default y - -config BT_AUDIO_RX - default y - -endif # AUDIO_DEV = 1 (HEADSET) - -# GATEWAY -if AUDIO_DEV = 2 - -config BT_CAP_INITIATOR - default y - -config BT_AUDIO_BROADCAST_NAME - default BT_AUDIO_BROADCAST_NAME_ALT if BT_AUDIO_USE_BROADCAST_NAME_ALT - -config BT_DEVICE_APPEARANCE - # Broadcasting Device - 0x0885 - default 2181 - -config BT_ISO_BROADCASTER - default y - -config BT_BAP_BROADCAST_SOURCE - default y - -config BT_ISO_TX_BUF_COUNT - default 2 - -config BT_BAP_BROADCAST_SRC_STREAM_COUNT - default 2 - -config BT_ISO_MAX_CHAN - default 2 - -config BT_AUDIO_TX - default y - -endif # AUDIO_DEV = 2 (GATEWAY) +config BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + default 80 diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.c index 59d07456554..e61f4af6cd8 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.c @@ -16,7 +16,6 @@ #include <../subsys/bluetooth/audio/bap_endpoint.h> #include "macros_common.h" -#include "le_audio.h" #include "nrf5340_audio_common.h" #include "channel_assignment.h" @@ -64,9 +63,9 @@ static uint8_t active_stream_index; static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( BT_AUDIO_CODEC_CAPABILIY_FREQ, - (BT_AUDIO_CODEC_LC3_DURATION_10 | BT_AUDIO_CODEC_LC3_DURATION_PREFER_10), - BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN), - LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, BT_AUDIO_CONTEXT_TYPE_MEDIA); + (BT_AUDIO_CODEC_CAP_DURATION_10 | BT_AUDIO_CODEC_CAP_DURATION_PREFER_10), + BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN), + LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, BT_AUDIO_CONTEXT_TYPE_ANY); static struct bt_pacs_cap capabilities = { .codec_cap = &codec_cap, @@ -129,55 +128,53 @@ static void le_audio_event_publish(enum le_audio_evt_type event) static void print_codec(const struct audio_codec_info *codec) { - if (codec->id == BT_HCI_CODING_FORMAT_LC3) { - LOG_INF("Codec config for LC3:"); - LOG_INF("\tFrequency: %d Hz", codec->frequency); - LOG_INF("\tFrame Duration: %d us", codec->frame_duration_us); - LOG_INF("\tOctets per frame: %d (%d kbps)", codec->octets_per_sdu, codec->bitrate); - LOG_INF("\tFrames per SDU: %d", codec->blocks_per_sdu); - if (codec->chan_allocation >= 0) { - LOG_INF("\tChannel allocation: 0x%x", codec->chan_allocation); - } - } else { - LOG_WRN("Codec is not LC3, codec_id: 0x%2hhx", codec->id); + LOG_INF("Codec config for LC3:"); + LOG_INF("\tFrequency: %d Hz", codec->frequency); + LOG_INF("\tFrame Duration: %d us", codec->frame_duration_us); + LOG_INF("\tOctets per frame: %d (%d kbps)", codec->octets_per_sdu, codec->bitrate); + LOG_INF("\tFrames per SDU: %d", codec->blocks_per_sdu); + if (codec->chan_allocation >= 0) { + LOG_INF("\tChannel allocation: 0x%x", codec->chan_allocation); } } static void get_codec_info(const struct bt_audio_codec_cfg *codec, struct audio_codec_info *codec_info) { - if (codec->id == BT_HCI_CODING_FORMAT_LC3) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - LOG_DBG("Retrieve the codec configuration for LC3"); - codec_info->id = codec->id; - codec_info->cid = codec->cid; - codec_info->vid = codec->vid; - codec_info->frequency = bt_audio_codec_cfg_get_freq(codec); - codec_info->frame_duration_us = bt_audio_codec_cfg_get_frame_dur(codec); - bt_audio_codec_cfg_get_chan_allocation(codec, &codec_info->chan_allocation); - codec_info->octets_per_sdu = bt_audio_codec_cfg_get_octets_per_frame(codec); - codec_info->bitrate = - (codec_info->octets_per_sdu * 8 * 1000000) / codec_info->frame_duration_us; - codec_info->blocks_per_sdu = - bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec, true); - } else { - LOG_WRN("Codec is not LC3, codec_id: 0x%2hhx", codec->id); + int ret; + + ret = le_audio_freq_hz_get(codec, &codec_info->frequency); + if (ret) { + LOG_DBG("Failed retrieving sampling frequency: %d", ret); } -} -static bool bitrate_check(const struct bt_audio_codec_cfg *codec) -{ - uint32_t octets_per_sdu = bt_audio_codec_cfg_get_octets_per_frame(codec); + ret = le_audio_duration_us_get(codec, &codec_info->frame_duration_us); + if (ret) { + LOG_DBG("Failed retrieving frame duration: %d", ret); + } - if (octets_per_sdu < LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN)) { - LOG_WRN("Bitrate too low"); - return false; - } else if (octets_per_sdu > LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX)) { - LOG_WRN("Bitrate too high"); - return false; + ret = bt_audio_codec_cfg_get_chan_allocation(codec, &codec_info->chan_allocation); + if (ret == -ENODATA) { + /* Codec channel allocation not set, defaulting to 0 */ + codec_info->chan_allocation = 0; + } else if (ret) { + LOG_DBG("Failed retrieving channel allocation: %d", ret); } - return true; + ret = le_audio_octets_per_frame_get(codec, &codec_info->octets_per_sdu); + if (ret) { + LOG_DBG("Failed retrieving octets per frame: %d", ret); + } + + ret = le_audio_bitrate_get(codec, &codec_info->bitrate); + if (ret) { + LOG_DBG("Failed calculating bitrate: %d", ret); + } + + ret = le_audio_frame_blocks_per_sdu_get(codec, &codec_info->blocks_per_sdu); + if (codec_info->octets_per_sdu < 0) { + LOG_DBG("Failed retrieving frame blocks per SDU: %d", codec_info->octets_per_sdu); + } } static void stream_started_cb(struct bt_bap_stream *stream) @@ -215,6 +212,10 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) break; + case BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL: + LOG_INF("MIC fail. The encryption key may be wrong"); + break; + default: LOG_WRN("Unhandled reason: %d", reason); @@ -249,96 +250,134 @@ static struct bt_bap_stream_ops stream_ops = { .recv = stream_recv_cb, }; -static bool parse_cb(struct bt_data *data, void *codec) +static bool base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis *bis, void *user_data) { - if (data->type == BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC) { - ((struct audio_codec_info *)codec)->chan_allocation = sys_get_le32(data->data); - return false; + int ret; + struct bt_audio_codec_cfg codec_cfg = {0}; + + LOG_DBG("BIS found, index %d", bis->index); + + ret = bt_bap_base_subgroup_bis_codec_to_codec_cfg(bis, &codec_cfg); + if (ret != 0) { + LOG_WRN("Could not find codec configuration for BIS index %d, ret " + "= %d", + bis->index, ret); + return true; + } + + get_codec_info(&codec_cfg, &audio_codec_info[bis->index - 1]); + + LOG_DBG("Channel allocation: 0x%x for BIS index %d", + audio_codec_info[bis->index - 1].chan_allocation, bis->index); + + uint32_t chan_bitfield = audio_codec_info[bis->index - 1].chan_allocation; + bool single_bit = (chan_bitfield & (chan_bitfield - 1)) == 0; + + if (single_bit) { + bis_index_bitfields[bis->index - 1] = BIT(bis->index); + } else { + LOG_WRN("More than one bit set in channel location, we only support 1 channel per " + "BIS"); } return true; } -/** - * @brief Function which overwrites BIS specific codec information. - * I.e. level 3 specific information overwrites general level 2 information. - * - * @note This will change when new host APIs are available. - * - * @return 0 for success, error otherwise. - */ -static int bis_specific_codec_config(struct bt_bap_base_bis_data bis_data, - struct audio_codec_info *codec) +static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data) { int ret; + int bis_num; + struct bt_audio_codec_cfg codec_cfg = {0}; + struct bt_bap_base_codec_id codec_id; + bool *suitable_stream_found = user_data; - ret = bt_audio_data_parse(bis_data.data, bis_data.data_len, parse_cb, codec); - if (ret && ret != -ECANCELED) { - LOG_WRN("Could not overwrite BIS specific codec info: %d", ret); - return -ENXIO; + ret = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &codec_cfg); + if (ret) { + LOG_WRN("Failed to convert codec to codec_cfg: %d", ret); + return true; } - return 0; + ret = bt_bap_base_get_subgroup_codec_id(subgroup, &codec_id); + if (ret && codec_id.cid != BT_HCI_CODING_FORMAT_LC3) { + LOG_WRN("Failed to get codec ID or codec ID is not supported: %d", ret); + return true; + } + + ret = le_audio_bitrate_check(&codec_cfg); + if (!ret) { + LOG_WRN("Bitrate check failed"); + return true; + } + + ret = le_audio_freq_check(&codec_cfg); + if (!ret) { + LOG_WRN("Sample rate not supported"); + return true; + } + + bis_num = bt_bap_base_get_subgroup_bis_count(subgroup); + LOG_DBG("Subgroup %p has %d BISes", (void *)subgroup, bis_num); + if (bis_num > 0) { + *suitable_stream_found = true; + sync_stream_cnt = bis_num; + for (int i = 0; i < bis_num; i++) { + get_codec_info(&codec_cfg, &audio_codec_info[i]); + } + + ret = bt_bap_base_subgroup_foreach_bis(subgroup, base_subgroup_bis_cb, NULL); + if (ret < 0) { + LOG_WRN("Could not get BIS for subgroup %p: %d", (void *)subgroup, ret); + } + return false; + } + + return true; } -static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base) +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base, + size_t base_size) { + int ret; bool suitable_stream_found = false; if (init_routine_completed) { return; } - LOG_DBG("Received BASE with %zu subgroup(s) from broadcast sink", base->subgroup_count); - sync_stream_cnt = 0; - /* Search each subgroup for the BIS of interest */ - for (int i = 0; i < base->subgroup_count; i++) { - for (int j = 0; j < base->subgroups[i].bis_count; j++) { - const uint8_t index = base->subgroups[i].bis_data[j].index; - - LOG_DBG("Subgroup: %d BIS: %d index = %d", i, j, index); - - if (bitrate_check(&base->subgroups[i].codec_cfg)) { - suitable_stream_found = true; - - bis_index_bitfields[sync_stream_cnt] = BIT(index); + uint32_t subgroup_count = bt_bap_base_get_subgroup_count(base); - /* Get general (level 2) codec config from the subgroup */ - audio_streams[sync_stream_cnt].codec_cfg = - (struct bt_audio_codec_cfg *)&base->subgroups[i].codec_cfg; - get_codec_info(audio_streams[sync_stream_cnt].codec_cfg, - &audio_codec_info[sync_stream_cnt]); + LOG_DBG("Received BASE with %d subgroup(s) from broadcast sink", subgroup_count); - /* Overwrite codec config with level 3 BIS specific codec config. - * For now, this is only done for channel allocation - */ - (void)bis_specific_codec_config(base->subgroups[i].bis_data[j], - &audio_codec_info[sync_stream_cnt]); - - LOG_DBG("Stream %d in subgroup %d from broadcast sink", - sync_stream_cnt, i); - - sync_stream_cnt += 1; - if (sync_stream_cnt >= ARRAY_SIZE(audio_streams)) { - break; - } - } - } - - if (sync_stream_cnt >= ARRAY_SIZE(audio_streams)) { - break; - } + ret = bt_bap_base_foreach_subgroup(base, base_subgroup_cb, &suitable_stream_found); + if (ret != 0 && ret != -ECANCELED) { + LOG_WRN("Failed to parse subgroups: %d", ret); + return; } if (suitable_stream_found) { /* Set the initial active stream based on the defined channel of the device */ channel_assignment_get((enum audio_channel *)&active_stream_index); + + /** If the stream matching channel is not present, revert back to first BIS, e.g. + * mono stream but channel assignment is RIGHT + */ + if ((active_stream_index + 1) > sync_stream_cnt) { + LOG_WRN("BIS index: %d not found, reverting to first BIS", + (active_stream_index + 1)); + active_stream_index = 0; + } + active_stream.stream = &audio_streams[active_stream_index]; active_stream.codec = &audio_codec_info[active_stream_index]; - active_stream.pd = base->pd; - + ret = bt_bap_base_get_pres_delay(base); + if (ret == -EINVAL) { + LOG_WRN("Failed to get pres_delay: %d", ret); + active_stream.pd = 0; + } else { + active_stream.pd = ret; + } le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED); LOG_DBG("Channel %s active", @@ -376,9 +415,6 @@ static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) return; } - /* NOTE: The string below is used by the Nordic CI system */ - LOG_INF("Syncing to broadcast stream index %d", active_stream_index); - if (bis_index_bitfields[active_stream_index] == 0) { LOG_ERR("No bits set in bitfield"); return; @@ -388,6 +424,9 @@ static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) return; } + /* NOTE: The string below is used by the Nordic CI system */ + LOG_INF("Syncing to broadcast stream index %d", active_stream_index); + ret = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfields[active_stream_index], audio_streams_p, bis_encryption_key); diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.h index d4016134109..81dfc7c8ace 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_sink.h @@ -7,7 +7,7 @@ #ifndef _BROADCAST_SINK_H_ #define _BROADCAST_SINK_H_ -#include "le_audio.h" +#include "bt_le_audio_tx.h" /** * @brief Change the active audio stream if the broadcast isochronous group (BIG) contains diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.c index e14a322ab43..602700c64be 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.c @@ -18,6 +18,7 @@ #include <../subsys/bluetooth/audio/bap_endpoint.h> #include "macros_common.h" +#include "bt_le_audio_tx.h" #include "le_audio.h" #include "nrf5340_audio_common.h" @@ -33,77 +34,21 @@ BUILD_ASSERT(CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT <= 2, ZBUS_CHAN_DEFINE(le_audio_chan, struct le_audio_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, ZBUS_MSG_INIT(0)); -ZBUS_CHAN_DEFINE(sdu_ref_chan, struct sdu_ref_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, - ZBUS_MSG_INIT(0)); - -#if CONFIG_BT_AUDIO_BROADCAST_CONFIGURABLE -#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ - BT_BAP_LC3_PRESET_CONFIGURABLE( \ - BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, \ - BT_AUDIO_CONTEXT_TYPE_MEDIA, CONFIG_BT_AUDIO_BITRATE_BROADCAST_SRC) - -#elif CONFIG_BT_BAP_BROADCAST_16_2_1 -#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ - BT_BAP_LC3_BROADCAST_PRESET_16_2_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ - BT_AUDIO_LOCATION_FRONT_RIGHT, \ - BT_AUDIO_CONTEXT_TYPE_MEDIA) - -#elif CONFIG_BT_BAP_BROADCAST_24_2_1 -#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ - BT_BAP_LC3_BROADCAST_PRESET_24_2_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ - BT_AUDIO_LOCATION_FRONT_RIGHT, \ - BT_AUDIO_CONTEXT_TYPE_MEDIA) - -#elif CONFIG_BT_BAP_BROADCAST_16_2_2 -#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ - BT_BAP_LC3_BROADCAST_PRESET_16_2_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ - BT_AUDIO_LOCATION_FRONT_RIGHT, \ - BT_AUDIO_CONTEXT_TYPE_MEDIA) - -#elif CONFIG_BT_BAP_BROADCAST_24_2_2 -#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ - BT_BAP_LC3_BROADCAST_PRESET_24_2_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ - BT_AUDIO_LOCATION_FRONT_RIGHT, \ - BT_AUDIO_CONTEXT_TYPE_MEDIA) - -#else -#error Unsupported LC3 codec preset for broadcast -#endif /* CONFIG_BT_AUDIO_BROADCAST_CONFIGURABLE */ - -#define STANDARD_QUALITY_16KHZ 16000 -#define STANDARD_QUALITY_24KHZ 24000 -#define HIGH_QUALITY_48KHZ 48000 - -#define HCI_ISO_BUF_ALLOC_PER_CHAN 2 -/* For being able to dynamically define iso_tx_pools */ -#define NET_BUF_POOL_ITERATE(i, _) \ - NET_BUF_POOL_FIXED_DEFINE(iso_tx_pool_##i, HCI_ISO_BUF_ALLOC_PER_CHAN, \ - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); -#define NET_BUF_POOL_PTR_ITERATE(i, ...) IDENTITY(&iso_tx_pool_##i) -LISTIFY(CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT, NET_BUF_POOL_ITERATE, (;)) - -/* clang-format off */ -static struct net_buf_pool *iso_tx_pools[] = { LISTIFY(CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT, - NET_BUF_POOL_PTR_ITERATE, (,)) }; -/* clang-format on */ - static struct bt_cap_broadcast_source *broadcast_source; - static struct bt_cap_stream cap_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; - static struct bt_bap_lc3_preset lc3_preset = BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO; - static struct bt_le_ext_adv *adv; -static atomic_t iso_tx_pool_alloc[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; -static uint32_t seq_num[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; static bool initialized; static bool delete_broadcast_src; #if (CONFIG_AURACAST) -NET_BUF_SIMPLE_DEFINE(pba_buf, BT_UUID_SIZE_16 + 2); -static struct bt_data ext_ad[4]; +/* Make sure pba_buf is large enough for a 16bit UUID and meta data + * (any addition to pba_buf requires an increase of this value) + */ +NET_BUF_SIMPLE_DEFINE(pba_buf, BT_UUID_SIZE_16 + 8); +static struct bt_data ext_ad[5]; #else -static struct bt_data ext_ad[3]; +static struct bt_data ext_ad[4]; #endif /* (CONFIG_AURACAST) */ static struct bt_data per_ad[1]; @@ -119,24 +64,6 @@ static void le_audio_event_publish(enum le_audio_evt_type event) ERR_CHK(ret); } -static bool is_iso_buffer_full(uint8_t idx) -{ - /* net_buf_alloc allocates buffers for APP->NET transfer over HCI RPMsg, - * but when these buffers are released it is not guaranteed that the - * data has actually been sent. The data might be qued on the NET core, - * and this can cause delays in the audio. - * When stream_sent_cb() is called the data has been sent. - * Data will be discarded if allocation becomes too high, to avoid audio delays. - * If the NET and APP core operates in clock sync, discarding should not occur. - */ - - if (atomic_get(&iso_tx_pool_alloc[idx]) >= HCI_ISO_BUF_ALLOC_PER_CHAN) { - return true; - } - - return false; -} - static int get_stream_index(struct bt_bap_stream *stream, uint8_t *index) { for (int i = 0; i < ARRAY_SIZE(cap_streams); i++) { @@ -153,22 +80,10 @@ static int get_stream_index(struct bt_bap_stream *stream, uint8_t *index) static void stream_sent_cb(struct bt_bap_stream *stream) { - static uint32_t sent_cnt[ARRAY_SIZE(cap_streams)]; uint8_t index = 0; get_stream_index(stream, &index); - - if (atomic_get(&iso_tx_pool_alloc[index])) { - atomic_dec(&iso_tx_pool_alloc[index]); - } else { - LOG_WRN("Decreasing atomic variable for stream %d failed", index); - } - - sent_cnt[index]++; - - if ((sent_cnt[index] % 1000U) == 0U) { - LOG_DBG("Sent %d total ISO packets on stream %d", sent_cnt[index], index); - } + ERR_CHK(bt_le_audio_tx_stream_sent(index)); } static void stream_started_cb(struct bt_bap_stream *stream) @@ -176,20 +91,27 @@ static void stream_started_cb(struct bt_bap_stream *stream) uint8_t index = 0; get_stream_index(stream, &index); - seq_num[index] = 0; + ERR_CHK(bt_le_audio_tx_stream_started(index)); le_audio_event_publish(LE_AUDIO_EVT_STREAMING); /* NOTE: The string below is used by the Nordic CI system */ LOG_INF("Broadcast source %p started", (void *)stream); + + le_audio_print_codec(stream->codec_cfg, BT_AUDIO_DIR_SOURCE); } static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) { int ret; + uint8_t index = 0; + + get_stream_index(stream, &index); le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING); + ERR_CHK(bt_le_audio_tx_stream_stopped(index)); + LOG_INF("Broadcast source %p stopped. Reason: %d", (void *)stream, reason); if (delete_broadcast_src && broadcast_source != NULL) { @@ -228,9 +150,9 @@ static void public_broadcast_features_set(uint8_t *features) *features |= 0x01; } - if (freq == STANDARD_QUALITY_16KHZ || freq == STANDARD_QUALITY_24KHZ) { + if (freq == BT_AUDIO_CODEC_CFG_FREQ_16KHZ || freq == BT_AUDIO_CODEC_CFG_FREQ_24KHZ) { *features |= 0x02; - } else if (freq == HIGH_QUALITY_48KHZ) { + } else if (freq == BT_AUDIO_CODEC_CFG_FREQ_48KHZ) { *features |= 0x04; } else { LOG_WRN("%dkHz is not compatible with Auracast, choose 16kHz, 24kHz or 48kHz", @@ -248,9 +170,17 @@ static int adv_create(void) NET_BUF_SIMPLE_DEFINE_STATIC(brdcst_id_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); /* Buffer for Appearance */ NET_BUF_SIMPLE_DEFINE_STATIC(brdcst_appearance_buf, BT_UUID_SIZE_16); + /* Buffer for manufacturer ID */ + NET_BUF_SIMPLE_DEFINE_STATIC(manufacturer_id_buf, BT_UUID_SIZE_16); /* Buffer for Public Broadcast Announcement */ NET_BUF_SIMPLE_DEFINE_STATIC(base_buf, 128); + net_buf_simple_add_le16(&manufacturer_id_buf, CONFIG_BT_DEVICE_MANUFACTURER_ID); + + ext_ad[0].data_len = manufacturer_id_buf.len; + ext_ad[0].type = BT_DATA_UUID16_SOME; + ext_ad[0].data = manufacturer_id_buf.data; + if (IS_ENABLED(CONFIG_BT_AUDIO_USE_BROADCAST_ID_RANDOM)) { ret = bt_cap_initiator_broadcast_get_id(broadcast_source, &broadcast_id); if (ret) { @@ -261,22 +191,29 @@ static int adv_create(void) broadcast_id = CONFIG_BT_AUDIO_BROADCAST_ID_FIXED; } - ext_ad[0] = (struct bt_data)BT_DATA(BT_DATA_BROADCAST_NAME, CONFIG_BT_AUDIO_BROADCAST_NAME, - sizeof(CONFIG_BT_AUDIO_BROADCAST_NAME) - 1); + if (IS_ENABLED(CONFIG_BT_AUDIO_USE_BROADCAST_NAME_ALT)) { + ext_ad[1] = (struct bt_data)BT_DATA(BT_DATA_BROADCAST_NAME, + CONFIG_BT_AUDIO_BROADCAST_NAME_ALT, + sizeof(CONFIG_BT_AUDIO_BROADCAST_NAME_ALT) - 1); + } else { + ext_ad[1] = (struct bt_data)BT_DATA(BT_DATA_BROADCAST_NAME, + CONFIG_BT_AUDIO_BROADCAST_NAME, + sizeof(CONFIG_BT_AUDIO_BROADCAST_NAME) - 1); + } /* Setup extended advertising data */ net_buf_simple_add_le16(&brdcst_id_buf, BT_UUID_BROADCAST_AUDIO_VAL); net_buf_simple_add_le24(&brdcst_id_buf, broadcast_id); - ext_ad[1].data_len = brdcst_id_buf.len; - ext_ad[1].type = BT_DATA_SVC_DATA16; - ext_ad[1].data = brdcst_id_buf.data; + ext_ad[2].data_len = brdcst_id_buf.len; + ext_ad[2].type = BT_DATA_SVC_DATA16; + ext_ad[2].data = brdcst_id_buf.data; net_buf_simple_add_le16(&brdcst_appearance_buf, CONFIG_BT_DEVICE_APPEARANCE); - ext_ad[2].data_len = brdcst_appearance_buf.len; - ext_ad[2].type = BT_DATA_GAP_APPEARANCE; - ext_ad[2].data = brdcst_appearance_buf.data; + ext_ad[3].data_len = brdcst_appearance_buf.len; + ext_ad[3].type = BT_DATA_GAP_APPEARANCE; + ext_ad[3].data = brdcst_appearance_buf.data; #if (CONFIG_AURACAST) uint8_t pba_features = 0; @@ -284,12 +221,32 @@ static int adv_create(void) net_buf_simple_add_le16(&pba_buf, 0x1856); net_buf_simple_add_u8(&pba_buf, pba_features); - /* No metadata, set length to 0 */ - net_buf_simple_add_u8(&pba_buf, 0x00); - ext_ad[3].data_len = pba_buf.len; - ext_ad[3].type = BT_DATA_SVC_DATA16; - ext_ad[3].data = pba_buf.data; + /* Metadata */ + /* 3 bytes for parental_rating and 3 bytes for active_flag LTVs */ + net_buf_simple_add_u8(&pba_buf, 0x06); + + /* Parental rating*/ + /* Length */ + net_buf_simple_add_u8(&pba_buf, 0x02); + /* Type */ + net_buf_simple_add_u8(&pba_buf, BT_AUDIO_METADATA_TYPE_PARENTAL_RATING); + /* Value */ + net_buf_simple_add_u8(&pba_buf, CONFIG_BT_AUDIO_BROADCAST_PARENTAL_RATING); + + /* Active flag */ + /* Length */ + net_buf_simple_add_u8(&pba_buf, 0x02); + /* Type */ + net_buf_simple_add_u8(&pba_buf, BT_AUDIO_METADATA_TYPE_AUDIO_STATE); + /* Value */ + net_buf_simple_add_u8(&pba_buf, BT_AUDIO_ACTIVE_STATE_ENABLED); + + /* If any additional data is to be added, remember to increase NET_BUF size */ + + ext_ad[4].data_len = pba_buf.len; + ext_ad[4].type = BT_DATA_SVC_DATA16; + ext_ad[4].data = pba_buf.data; #endif /* (CONFIG_AURACAST) */ /* Setup periodic advertising data */ @@ -317,7 +274,7 @@ static void bt_audio_codec_allocation_set(uint8_t *data, uint8_t data_len, enum bt_audio_location loc) { data[0] = data_len - 1; - data[1] = BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC; + data[1] = BT_AUDIO_CODEC_CFG_CHAN_ALLOC; sys_put_le32((const uint32_t)loc, &data[2]); } @@ -396,81 +353,15 @@ int broadcast_source_stop(void) int broadcast_source_send(struct le_audio_encoded_audio enc_audio) { int ret; - static bool wrn_printed[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; - struct net_buf *buf; - size_t num_streams = ARRAY_SIZE(cap_streams); - size_t data_size_pr_stream; - struct bt_iso_tx_info tx_info = {0}; - struct sdu_ref_msg msg; - - if ((enc_audio.num_ch == 1) || (enc_audio.num_ch == num_streams)) { - data_size_pr_stream = enc_audio.size / enc_audio.num_ch; - } else { - LOG_ERR("Num enc channels is %d Must be 1 or num streams", enc_audio.num_ch); - return -EINVAL; - } - - if (data_size_pr_stream != LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE)) { - LOG_ERR("The encoded data size does not match the SDU size"); - return -ECANCELED; - } - - for (int i = 0; i < num_streams; i++) { - if (cap_streams[i].bap_stream.ep->status.state != BT_BAP_EP_STATE_STREAMING) { - LOG_DBG("Stream %d not in streaming state", i); - continue; - } - - if (is_iso_buffer_full(i)) { - if (!wrn_printed[i]) { - LOG_WRN("HCI ISO TX overrun on ch %d - Single print", i); - wrn_printed[i] = true; - } - - return -ENOMEM; - } + struct bt_bap_stream *bap_tx_streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; - wrn_printed[i] = false; - - buf = net_buf_alloc(iso_tx_pools[i], K_NO_WAIT); - if (buf == NULL) { - /* This should never occur because of the is_iso_buffer_full() check */ - LOG_WRN("Out of TX buffers"); - return -ENOMEM; - } - - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - if (enc_audio.num_ch == 1) { - net_buf_add_mem(buf, &enc_audio.data[0], data_size_pr_stream); - } else { - net_buf_add_mem(buf, &enc_audio.data[i * data_size_pr_stream], - data_size_pr_stream); - } - - atomic_inc(&iso_tx_pool_alloc[i]); - - ret = bt_bap_stream_send(&cap_streams[i].bap_stream, buf, seq_num[i]++, - BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - LOG_WRN("Failed to send audio data: %d", ret); - net_buf_unref(buf); - atomic_dec(&iso_tx_pool_alloc[i]); - return ret; - } + for (int i = 0; i < ARRAY_SIZE(cap_streams); i++) { + bap_tx_streams[i] = &cap_streams[i].bap_stream; } - ret = bt_iso_chan_get_tx_sync(&cap_streams[0].bap_stream.ep->iso->chan, &tx_info); - + ret = bt_le_audio_tx_send(bap_tx_streams, enc_audio, ARRAY_SIZE(cap_streams)); if (ret) { - LOG_DBG("Error getting ISO TX anchor point: %d", ret); - } else { - msg.timestamp = tx_info.ts; - msg.adjust = false; - - ret = zbus_chan_pub(&sdu_ref_chan, &msg, K_NO_WAIT); - if (ret) { - LOG_WRN("Failed to publish timestamp: %d", ret); - } + return ret; } return 0; @@ -519,6 +410,11 @@ int broadcast_source_enable(void) return -EALREADY; } + ret = bt_le_audio_tx_init(); + if (ret) { + return ret; + } + LOG_INF("Enabling broadcast_source %s", CONFIG_BT_AUDIO_BROADCAST_NAME); (void)memset(cap_streams, 0, sizeof(cap_streams)); @@ -545,9 +441,8 @@ int broadcast_source_enable(void) subgroup_params[i].stream_params = &stream_params[i]; subgroup_params[i].codec_cfg = &lc3_preset.codec_cfg; #if (CONFIG_BT_AUDIO_BROADCAST_IMMEDIATE_FLAG) - /* Immediate rendering flag */ - subgroup_params[i].codec_cfg->meta_len++; - subgroup_params[i].codec_cfg->meta[subgroup_params[i].codec_cfg->meta_len] = 0x09; + bt_audio_codec_cfg_meta_set_bcast_audio_immediate_rend_flag( + subgroup_params[i].codec_cfg); #endif /* (CONFIG_BT_AUDIO_BROADCAST_IMMEDIATE_FLAG) */ } diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.h index 71bed31b662..e2f14ab9f6e 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/broadcast/broadcast_source.h @@ -7,7 +7,75 @@ #ifndef _BROADCAST_SOURCE_H_ #define _BROADCAST_SOURCE_H_ -#include "le_audio.h" +#include "bt_le_audio_tx.h" + +#if CONFIG_BT_AUDIO_BROADCAST_CONFIGURABLE +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_PRESET_CONFIGURABLE( \ + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA, CONFIG_BT_AUDIO_BITRATE_BROADCAST_SRC) + +#elif CONFIG_BT_BAP_BROADCAST_16_2_1 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_16_2_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_16_2_2 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_16_2_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_24_2_1 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_24_2_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_24_2_2 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_24_2_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_48_2_1 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) +#elif CONFIG_BT_BAP_BROADCAST_48_2_2 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_2_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_48_4_1 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_4_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_48_4_2 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_4_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_48_6_1 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_6_1(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#elif CONFIG_BT_BAP_BROADCAST_48_6_2 +#define BT_BAP_LC3_BROADCAST_PRESET_NRF5340_AUDIO \ + BT_BAP_LC3_BROADCAST_PRESET_48_6_2(BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT, \ + BT_AUDIO_CONTEXT_TYPE_MEDIA) +#else +#error Unsupported LC3 codec preset for broadcast +#endif /* CONFIG_BT_AUDIO_BROADCAST_CONFIGURABLE */ /** * @brief Get the data to advertise. diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/CMakeLists.txt b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/CMakeLists.txt new file mode 100644 index 00000000000..e22ad9be396 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if (CONFIG_BT_AUDIO_TX) + target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/bt_le_audio_tx.c) +endif() diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.c new file mode 100644 index 00000000000..1811e4e0948 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bt_le_audio_tx.h" + +#include +#include +#include <../subsys/bluetooth/audio/bap_stream.h> + +#include "nrf5340_audio_common.h" +#include "audio_sync_timer.h" +#include "sdc_hci_vs.h" + +#include +LOG_MODULE_REGISTER(bt_le_audio_tx, CONFIG_BLE_LOG_LEVEL); + +ZBUS_CHAN_DEFINE(sdu_ref_chan, struct sdu_ref_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, + ZBUS_MSG_INIT(0)); + +#ifdef CONFIG_BT_BAP_UNICAST_SERVER +#define SRC_STREAM_COUNT CONFIG_BT_ASCS_ASE_SRC_COUNT +#elif CONFIG_BT_BAP_UNICAST_CLIENT +#define SRC_STREAM_COUNT CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT +#elif CONFIG_BT_BAP_BROADCAST_SOURCE +#define SRC_STREAM_COUNT CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT +#else +#define SRC_STREAM_COUNT 0 +#endif + +#define HANDLE_INVALID 0xFFFF + +#define HCI_ISO_BUF_ALLOC_PER_CHAN 2 + +/* For being able to dynamically define iso_tx_pools */ +#define NET_BUF_POOL_ITERATE(i, _) \ + NET_BUF_POOL_FIXED_DEFINE(iso_tx_pool_##i, HCI_ISO_BUF_ALLOC_PER_CHAN, \ + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); +#define NET_BUF_POOL_PTR_ITERATE(i, ...) IDENTITY(&iso_tx_pool_##i) +LISTIFY(SRC_STREAM_COUNT, NET_BUF_POOL_ITERATE, (;)) +/* clang-format off */ +static struct net_buf_pool *iso_tx_pools[] = { LISTIFY(SRC_STREAM_COUNT, + NET_BUF_POOL_PTR_ITERATE, (,)) }; +/* clang-format on */ + +struct tx_inf { + uint16_t iso_conn_handle; + struct bt_iso_tx_info iso_tx; + struct bt_iso_tx_info iso_tx_readback; + struct net_buf_pool *iso_tx_pool; + atomic_t iso_tx_pool_alloc; + bool hci_wrn_printed; +}; + +static bool initialized; +static struct tx_inf tx_info_arr[SRC_STREAM_COUNT]; + +/** + * @brief Sends audio data over a single BAP stream. + * + * @param data Audio data to send. + * @param size Size of data. + * @param bap_stream Pointer to BAP stream to use. + * @param tx_info Pointer to tx_info struct. + * @param ts_tx Timestamp to send. Note that for some controllers, BT_ISO_TIMESTAMP_NONE + * is used. This timestamp is used to ensure that SDUs are sent in the same + * connection interval. + * @return 0 if successful, error otherwise. + */ +static int iso_stream_send(uint8_t const *const data, size_t size, struct bt_bap_stream *bap_stream, + struct tx_inf *tx_info, uint32_t ts_tx) +{ + int ret; + struct net_buf *buf; + + /* net_buf_alloc allocates buffers for APP->NET transfer over HCI RPMsg, + * but when these buffers are released it is not guaranteed that the + * data has actually been sent. The data might be queued on the NET core, + * and this can cause delays in the audio. + * When the sent callback is called the data has been sent, and we can free the buffer. + * Data will be discarded if allocation becomes too high, to avoid audio delays. + * If the NET and APP core operates in clock sync, discarding should not occur. + */ + if (atomic_get(&tx_info->iso_tx_pool_alloc) >= HCI_ISO_BUF_ALLOC_PER_CHAN) { + if (!tx_info->hci_wrn_printed) { + struct bt_iso_chan *iso_chan; + + iso_chan = bt_bap_stream_iso_chan_get(bap_stream); + + LOG_WRN("HCI ISO TX overrun on stream %p - Single print", + (void *)bap_stream); + tx_info->hci_wrn_printed = true; + } + return -ENOMEM; + } + + tx_info->hci_wrn_printed = false; + + buf = net_buf_alloc(tx_info->iso_tx_pool, K_NO_WAIT); + if (buf == NULL) { + /* This should never occur because of the iso_tx_pool_alloc check above */ + LOG_WRN("Out of TX buffers"); + return -ENOMEM; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, data, size); + + atomic_inc(&tx_info->iso_tx_pool_alloc); + + if (ts_tx == 0) { + ret = bt_bap_stream_send(bap_stream, buf, tx_info->iso_tx.seq_num); + } else { + ret = bt_bap_stream_send_ts(bap_stream, buf, tx_info->iso_tx.seq_num, ts_tx); + } + + if (ret < 0) { + if (ret != -ENOTCONN) { + LOG_WRN("Failed to send audio data: %d stream %p", ret, bap_stream); + } + net_buf_unref(buf); + atomic_dec(&tx_info->iso_tx_pool_alloc); + return ret; + } else { + tx_info->iso_tx.seq_num++; + } + + return 0; +} + +static int get_tx_sync_sdc(uint16_t iso_conn_handle, struct bt_iso_tx_info *info) +{ + int ret; + struct net_buf *buf; + struct net_buf *rsp; + sdc_hci_cmd_vs_iso_read_tx_timestamp_t *cmd_read_tx_timestamp; + + buf = bt_hci_cmd_create(SDC_HCI_OPCODE_CMD_VS_ISO_READ_TX_TIMESTAMP, + sizeof(*cmd_read_tx_timestamp)); + if (!buf) { + LOG_ERR("Could not allocate command buffer"); + return -ENOBUFS; + } + + cmd_read_tx_timestamp = net_buf_add(buf, sizeof(*cmd_read_tx_timestamp)); + cmd_read_tx_timestamp->conn_handle = iso_conn_handle; + + ret = bt_hci_cmd_send_sync(SDC_HCI_OPCODE_CMD_VS_ISO_READ_TX_TIMESTAMP, buf, &rsp); + if (ret) { + return ret; + } + + if (rsp) { + sdc_hci_cmd_vs_iso_read_tx_timestamp_return_t *rsp_params = (void *)&rsp->data[1]; + + info->ts = rsp_params->tx_time_stamp; + info->seq_num = rsp_params->packet_sequence_number; + info->offset = 0; + + net_buf_unref(rsp); + return 0; + } + + return -EINVAL; +} + +static int iso_conn_handle_set(struct bt_bap_stream *bap_stream, uint16_t *iso_conn_handle) +{ + int ret; + + if (*iso_conn_handle == HANDLE_INVALID) { + struct bt_bap_ep_info ep_info; + + ret = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (ret) { + LOG_WRN("Unable to get info for ep"); + return -EACCES; + } + + ret = bt_hci_get_conn_handle(ep_info.iso_chan->iso, + iso_conn_handle); + if (ret) { + LOG_ERR("Failed obtaining conn_handle (ret:%d)", ret); + return ret; + } + } else { + /* Already set. */ + } + + return 0; +} + +int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_encoded_audio enc_audio, + uint8_t streams_to_tx) +{ + int ret; + size_t data_size_pr_stream = 0; + + if (!initialized) { + return -EACCES; + } + + if (bap_streams == NULL) { + return -EINVAL; + } + + if (streams_to_tx == 0) { + LOG_INF("No active streams"); + return 0; + } + + if (streams_to_tx > SRC_STREAM_COUNT) { + return -ENOMEM; + } + + if ((enc_audio.num_ch == 1) || (enc_audio.num_ch == streams_to_tx)) { + data_size_pr_stream = enc_audio.size / enc_audio.num_ch; + } else { + LOG_ERR("Num encoded channels: %d must be 1 or equal to num streams: %d", + enc_audio.num_ch, streams_to_tx); + return -EINVAL; + } + + /* When sending ISO data, we always send ts = 0 to the first active transmitting channel. + * The controller will populate with a ts which is fetched using bt_iso_chan_get_tx_sync. + * This timestamp will be submitted to all the other channels in order to place data on all + * channels in the same ISO interval. + */ + + uint32_t common_tx_sync_ts_us = 0; + uint32_t curr_ts_us = 0; + bool ts_common_acquired = false; + uint32_t common_interval = 0; + + for (int i = 0; i < streams_to_tx; i++) { + if (tx_info_arr[i].iso_tx.seq_num == 0) { + /* Temporary fix until /zephyr/pull/68745/ is available + */ +#if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM) + bap_streams[i]->_prev_seq_num = 0; +#endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */ + } + + if (!le_audio_ep_state_check(bap_streams[i]->ep, BT_BAP_EP_STATE_STREAMING)) { + /* This bap_stream is not streaming*/ + continue; + } + + uint32_t bitrate; + + ret = le_audio_bitrate_get(bap_streams[i]->codec_cfg, &bitrate); + if (ret) { + LOG_ERR("Failed to calculate bitrate: %d", ret); + return ret; + } + + if (data_size_pr_stream != LE_AUDIO_SDU_SIZE_OCTETS(bitrate)) { + LOG_ERR("The encoded data size does not match the SDU size"); + return -EINVAL; + } + + if (common_interval != 0 && (common_interval != bap_streams[i]->qos->interval)) { + LOG_ERR("Not all channels have the same ISO interval"); + return -EINVAL; + } + common_interval = bap_streams[i]->qos->interval; + + /* Check if same audio is sent to all channels */ + if (enc_audio.num_ch == 1) { + ret = iso_stream_send(enc_audio.data, data_size_pr_stream, bap_streams[i], + &tx_info_arr[i], common_tx_sync_ts_us); + } else { + ret = iso_stream_send(&enc_audio.data[data_size_pr_stream * i], + data_size_pr_stream, bap_streams[i], &tx_info_arr[i], + common_tx_sync_ts_us); + } + + if (ret) { + /* DBG used here as prints are handled within iso_stream_send */ + LOG_DBG("Failed to send to idx: %d stream: %p, ret: %d ", i, bap_streams[i], + ret); + continue; + } + + ret = iso_conn_handle_set(bap_streams[i], &tx_info_arr[i].iso_conn_handle); + if (ret) { + continue; + } + + /* Strictly, it is only required to call get_tx_sync_sdc on the first streaming + * channel to get the timestamp which is sent to all other channels. + * However, to be able to detect errors, this is called on each TX. + */ + ret = get_tx_sync_sdc(tx_info_arr[i].iso_conn_handle, + &tx_info_arr[i].iso_tx_readback); + if (ret) { + if (ret != -ENOTCONN) { + LOG_WRN("Unable to get tx sync. ret: %d stream: %p", ret, + bap_streams[i]); + } + continue; + } + + if (!ts_common_acquired) { + curr_ts_us = audio_sync_timer_capture(); + common_tx_sync_ts_us = tx_info_arr[i].iso_tx_readback.ts; + ts_common_acquired = true; + } + } + + if (ts_common_acquired) { + struct sdu_ref_msg msg; + + msg.tx_sync_ts_us = common_tx_sync_ts_us; + msg.curr_ts_us = curr_ts_us; + msg.adjust = true; + + ret = zbus_chan_pub(&sdu_ref_chan, &msg, K_NO_WAIT); + if (ret) { + LOG_WRN("Failed to publish timestamp: %d", ret); + } + } + + return 0; +} + +int bt_le_audio_tx_stream_stopped(uint8_t stream_idx) +{ + if (!initialized) { + return -EACCES; + } + + atomic_clear(&tx_info_arr[stream_idx].iso_tx_pool_alloc); + + return 0; +} + +int bt_le_audio_tx_stream_started(uint8_t stream_idx) +{ + if (!initialized) { + return -EACCES; + } + + tx_info_arr[stream_idx].hci_wrn_printed = false; + tx_info_arr[stream_idx].iso_conn_handle = HANDLE_INVALID; + tx_info_arr[stream_idx].iso_tx.seq_num = 0; + tx_info_arr[stream_idx].iso_tx_readback.seq_num = 0; + return 0; +} + +int bt_le_audio_tx_stream_sent(uint8_t stream_idx) +{ + if (!initialized) { + return -EACCES; + } + + atomic_dec(&tx_info_arr[stream_idx].iso_tx_pool_alloc); + return 0; +} + +int bt_le_audio_tx_init(void) +{ + if (initialized) { + return -EALREADY; + } + + for (int i = 0; i < SRC_STREAM_COUNT; i++) { + tx_info_arr[i].iso_tx_pool = iso_tx_pools[i]; + tx_info_arr[i].hci_wrn_printed = false; + tx_info_arr[i].iso_conn_handle = HANDLE_INVALID; + tx_info_arr[i].iso_tx.ts = 0; + tx_info_arr[i].iso_tx.offset = 0; + tx_info_arr[i].iso_tx.seq_num = 0; + tx_info_arr[i].iso_tx_readback.ts = 0; + tx_info_arr[i].iso_tx_readback.offset = 0; + tx_info_arr[i].iso_tx_readback.seq_num = 0; + } + + initialized = true; + return 0; +} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.h new file mode 100644 index 00000000000..a5ff4c47fa8 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _LE_AUDIO_TX_H_ +#define _LE_AUDIO_TX_H_ + +#include +#include + +#include "le_audio.h" + +/** + * @brief Allocates buffers and sends data to the controller. + * + * @note Send all available channels in a single call. + * Do not call this for each channel. + * + * @param bap_streams Pointer to an array of BAP streams. + * @param enc_audio Encoded audio data. + * @param streams_to_tx Number of streams to send. + * + * @return 0 if successful, error otherwise. + */ +int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_encoded_audio enc_audio, + uint8_t streams_to_tx); + +/** + * @brief Resets TX buffers. Must be called when a TX stream is stopped. + * + * @param stream_idx Stream index + * + * @retval -EACCES The module has not been initialized. + * @retval 0 Success. + */ +int bt_le_audio_tx_stream_stopped(uint8_t stream_idx); + +/** + * @brief Initializes a stream. Must be called when a TX stream is started. + * + * @param stream_idx Stream index. + * + * @retval -EACCES The module has not been initialized. + * @retval 0 Success. + */ +int bt_le_audio_tx_stream_started(uint8_t stream_idx); + +/** + * @brief Frees a TX buffer. Must be called when a TX stream has been sent. + * + * @param stream_idx Stream index. + * + * @retval -EACCES The module has not been initialized. + * @retval 0 Success. + */ +int bt_le_audio_tx_stream_sent(uint8_t stream_idx); + +/** + * @brief Initializes the TX path for ISO transmission. + * + * @retval -EALREADY The module has already been initialized. + * @retval 0 Success. + */ +int bt_le_audio_tx_init(void); + +#endif /* _LE_AUDIO_TX_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c new file mode 100644 index 00000000000..6d03b400cb0 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "le_audio.h" + +#include +#include + +#include +LOG_MODULE_REGISTER(le_audio, CONFIG_BLE_LOG_LEVEL); + +/*TODO: Create helper function in host to perform this action. */ +bool le_audio_ep_state_check(struct bt_bap_ep *ep, enum bt_bap_ep_state state) +{ + int ret; + struct bt_bap_ep_info ep_info; + + if (ep == NULL) { + /* If an endpoint is NULL it is not in any of the states */ + return false; + } + + ret = bt_bap_ep_get_info(ep, &ep_info); + if (ret) { + LOG_WRN("Unable to get info for ep"); + return false; + } + + if (ep_info.state == state) { + return true; + } + + return false; +} + +int le_audio_freq_hz_get(const struct bt_audio_codec_cfg *codec, int *freq_hz) +{ + int ret; + + ret = bt_audio_codec_cfg_get_freq(codec); + if (ret < 0) { + return ret; + } + + ret = bt_audio_codec_cfg_freq_to_freq_hz(ret); + if (ret < 0) { + return ret; + } + + *freq_hz = ret; + + return 0; +} + +int le_audio_duration_us_get(const struct bt_audio_codec_cfg *codec, int *frame_dur_us) +{ + int ret; + + ret = bt_audio_codec_cfg_get_frame_dur(codec); + if (ret < 0) { + return ret; + } + + ret = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + if (ret < 0) { + return ret; + } + + *frame_dur_us = ret; + + return 0; +} + +int le_audio_octets_per_frame_get(const struct bt_audio_codec_cfg *codec, uint32_t *octets_per_sdu) +{ + int ret; + + ret = bt_audio_codec_cfg_get_octets_per_frame(codec); + if (ret < 0) { + return ret; + } + + *octets_per_sdu = ret; + + return 0; +} + +int le_audio_frame_blocks_per_sdu_get(const struct bt_audio_codec_cfg *codec, + uint32_t *frame_blks_per_sdu) +{ + int ret; + + ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec, true); + if (ret < 0) { + return ret; + } + + *frame_blks_per_sdu = ret; + + return 0; +} + +int le_audio_bitrate_get(const struct bt_audio_codec_cfg *const codec, uint32_t *bitrate) +{ + int ret; + int dur_us; + + ret = le_audio_duration_us_get(codec, &dur_us); + if (ret) { + return ret; + } + + int frames_per_sec = 1000000 / dur_us; + int octets_per_sdu; + + ret = le_audio_octets_per_frame_get(codec, &octets_per_sdu); + if (ret) { + return ret; + } + + *bitrate = frames_per_sec * (octets_per_sdu * 8); + + return 0; +} + +int le_audio_stream_dir_get(struct bt_bap_stream const *const stream) +{ + int ret; + struct bt_bap_ep_info ep_info; + + ret = bt_bap_ep_get_info(stream->ep, &ep_info); + + if (ret) { + LOG_WRN("Failed to get ep_info"); + return ret; + } + + return ep_info.dir; +} + +bool le_audio_bitrate_check(const struct bt_audio_codec_cfg *codec) +{ + int ret; + uint32_t octets_per_sdu; + + ret = le_audio_octets_per_frame_get(codec, &octets_per_sdu); + if (ret) { + LOG_ERR("Error retrieving octets per frame: %d", ret); + return false; + } + + if (octets_per_sdu < LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN)) { + LOG_WRN("Bitrate too low"); + return false; + } else if (octets_per_sdu > LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX)) { + LOG_WRN("Bitrate too high"); + return false; + } + + return true; +} + +bool le_audio_freq_check(const struct bt_audio_codec_cfg *codec) +{ + int ret; + uint32_t frequency_hz; + + ret = le_audio_freq_hz_get(codec, &frequency_hz); + if (ret) { + LOG_ERR("Error retrieving sampling rate: %d", ret); + return false; + } + + switch (frequency_hz) { + case 8000U: + return (BT_AUDIO_CODEC_CAP_FREQ_8KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 11025U: + return (BT_AUDIO_CODEC_CAP_FREQ_11KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 16000U: + return (BT_AUDIO_CODEC_CAP_FREQ_16KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 22050U: + return (BT_AUDIO_CODEC_CAP_FREQ_22KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 24000U: + return (BT_AUDIO_CODEC_CAP_FREQ_24KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 32000U: + return (BT_AUDIO_CODEC_CAP_FREQ_32KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 44100U: + return (BT_AUDIO_CODEC_CAP_FREQ_44KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 48000U: + return (BT_AUDIO_CODEC_CAP_FREQ_48KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 88200U: + return (BT_AUDIO_CODEC_CAP_FREQ_88KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 96000U: + return (BT_AUDIO_CODEC_CAP_FREQ_96KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 176400U: + return (BT_AUDIO_CODEC_CAP_FREQ_176KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 192000U: + return (BT_AUDIO_CODEC_CAP_FREQ_192KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + case 384000U: + return (BT_AUDIO_CODEC_CAP_FREQ_384KHZ & (BT_AUDIO_CODEC_CAPABILIY_FREQ)); + default: + return false; + } +} + +void le_audio_print_codec(const struct bt_audio_codec_cfg *codec, enum bt_audio_dir dir) +{ + if (codec->id == BT_HCI_CODING_FORMAT_LC3) { + /* LC3 uses the generic LTV format - other codecs might do as well */ + int ret; + enum bt_audio_location chan_allocation; + int freq_hz; + int dur_us; + uint32_t octets_per_sdu; + int frame_blks_per_sdu; + uint32_t bitrate; + + ret = le_audio_freq_hz_get(codec, &freq_hz); + if (ret) { + LOG_ERR("Error retrieving sampling frequency: %d", ret); + return; + } + + ret = le_audio_duration_us_get(codec, &dur_us); + if (ret) { + LOG_ERR("Error retrieving frame duration: %d", ret); + return; + } + + ret = le_audio_octets_per_frame_get(codec, &octets_per_sdu); + if (ret) { + LOG_ERR("Error retrieving octets per frame: %d", ret); + return; + } + + ret = le_audio_frame_blocks_per_sdu_get(codec, &frame_blks_per_sdu); + if (ret) { + LOG_ERR("Error retrieving frame blocks per SDU: %d", ret); + return; + } + + ret = bt_audio_codec_cfg_get_chan_allocation(codec, &chan_allocation); + if (ret == -ENODATA) { + /* Codec channel allocation not set, defaulting to 0 */ + chan_allocation = 0; + } else if (ret) { + LOG_ERR("Error retrieving channel allocation: %d", ret); + return; + } + + ret = le_audio_bitrate_get(codec, &bitrate); + if (ret) { + LOG_ERR("Unable to calculate bitrate: %d", ret); + return; + } + + if (dir == BT_AUDIO_DIR_SINK) { + LOG_INF("LC3 codec config for sink:"); + } else if (dir == BT_AUDIO_DIR_SOURCE) { + LOG_INF("LC3 codec config for source:"); + } else { + LOG_INF("LC3 codec config for :"); + } + + LOG_INF("\tFrequency: %d Hz", freq_hz); + LOG_INF("\tDuration: %d us", dur_us); + LOG_INF("\tChannel allocation: 0x%x", chan_allocation); + LOG_INF("\tOctets per frame: %d (%d bps)", octets_per_sdu, bitrate); + LOG_INF("\tFrames per SDU: %d", frame_blks_per_sdu); + } else { + LOG_WRN("Codec is not LC3, codec_id: 0x%2x", codec->id); + } +} diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h new file mode 100644 index 00000000000..47b7e2c0280 --- /dev/null +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef _LE_AUDIO_H_ +#define _LE_AUDIO_H_ + +#include +#include + +#define LE_AUDIO_ZBUS_EVENT_WAIT_TIME K_MSEC(5) +#define LE_AUDIO_SDU_SIZE_OCTETS(bitrate) (bitrate / (1000000 / CONFIG_AUDIO_FRAME_DURATION_US) / 8) + +#if CONFIG_SAMPLE_RATE_CONVERTER && CONFIG_AUDIO_SAMPLE_RATE_48000_HZ +#define BT_AUDIO_CODEC_CAPABILIY_FREQ \ + BT_AUDIO_CODEC_CAP_FREQ_48KHZ | BT_AUDIO_CODEC_CAP_FREQ_24KHZ | \ + BT_AUDIO_CODEC_CAP_FREQ_16KHZ + +#elif CONFIG_AUDIO_SAMPLE_RATE_16000_HZ +#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_CAP_FREQ_16KHZ + +#elif CONFIG_AUDIO_SAMPLE_RATE_24000_HZ +#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_CAP_FREQ_24KHZ + +#elif CONFIG_AUDIO_SAMPLE_RATE_48000_HZ +#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_CAP_FREQ_48KHZ + +#else +#error No sample rate supported +#endif /* CONFIG_SAMPLE_RATE_CONVERTER */ + +#define BT_BAP_LC3_PRESET_CONFIGURABLE(_loc, _stream_context, _bitrate) \ + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG(CONFIG_BT_AUDIO_PREF_SAMPLE_RATE_VALUE, \ + BT_AUDIO_CODEC_CFG_DURATION_10, _loc, \ + LE_AUDIO_SDU_SIZE_OCTETS(_bitrate), 1, \ + _stream_context), \ + BT_AUDIO_CODEC_QOS_UNFRAMED(10000u, LE_AUDIO_SDU_SIZE_OCTETS(_bitrate), \ + CONFIG_BT_AUDIO_RETRANSMITS, \ + CONFIG_BT_AUDIO_MAX_TRANSPORT_LATENCY_MS, \ + CONFIG_BT_AUDIO_PRESENTATION_DELAY_US)) + +/** + * @brief Callback for receiving Bluetooth LE Audio data. + * + * @param data Pointer to received data. + * @param size Size of received data. + * @param bad_frame Indicating if the frame is a bad frame or not. + * @param sdu_ref ISO timestamp. + * @param channel_index Audio channel index. + */ +typedef void (*le_audio_receive_cb)(const uint8_t *const data, size_t size, bool bad_frame, + uint32_t sdu_ref, enum audio_channel channel_index, + size_t desired_size); + +/** + * @brief Encoded audio data and information. + * + * @note Container for SW codec (typically LC3) compressed audio data. + */ +struct le_audio_encoded_audio { + uint8_t const *const data; + size_t size; + uint8_t num_ch; +}; + +/** + * @brief Check if an endpoint is in the given state. + * If the endpoint is NULL, it is not in the + * given state, and this function returns false. + * + * @param[in] ep The endpoint to check. + * @param[in] state The state to check for. + * + * @retval true The endpoint is in the given state. + * @retval false Otherwise. + */ +bool le_audio_ep_state_check(struct bt_bap_ep *ep, enum bt_bap_ep_state state); + +/** + * @brief Decode the audio sampling frequency in the codec configuration. + * + * @param[in] codec Pointer to the audio codec structure. + * @param[out] freq_hz Pointer to the sampling frequency in Hz. + * + * @return 0 for success, error otherwise. + */ +int le_audio_freq_hz_get(const struct bt_audio_codec_cfg *codec, int *freq_hz); + +/** + * @brief Decode the audio frame duration in us in the codec configuration. + * + * @param[in] codec Pointer to the audio codec structure. + * @param[out] frame_dur_us Pointer to the frame duration in us. + * + * @return 0 for success, error otherwise. + */ +int le_audio_duration_us_get(const struct bt_audio_codec_cfg *codec, int *frame_dur_us); + +/** + * @brief Decode the number of octets per frame in the codec configuration. + * + * @param[in] codec Pointer to the audio codec structure. + * @param[out] octets_per_sdu Pointer to the number of octets per SDU. + * + * @return 0 for success, error otherwise. + */ +int le_audio_octets_per_frame_get(const struct bt_audio_codec_cfg *codec, uint32_t *octets_per_sdu); + +/** + * @brief Decode the number of frame blocks per SDU in the codec configuration. + * + * @param[in] codec Pointer to the audio codec structure. + * @param[out] frame_blks_per_sdu Pointer to the number of frame blocks per SDU. + * + * @return 0 for success, error otherwise. + */ +int le_audio_frame_blocks_per_sdu_get(const struct bt_audio_codec_cfg *codec, + uint32_t *frame_blks_per_sdu); + +/** + * @brief Get the bitrate for the codec configuration. + * + * @details Decodes the audio frame duration and the number of octets per fram from the codec + * configuration, and calculates the bitrate. + * + * @param[in] codec Pointer to the audio codec structure. + * @param[out] bitrate Pointer to the bitrate in bps. + */ +int le_audio_bitrate_get(const struct bt_audio_codec_cfg *const codec, uint32_t *bitrate); + +/** + * @brief Get the direction of the @p stream provided. + * + * @param[in] stream Stream to check direction for. + * + * @retval BT_AUDIO_DIR_SINK sink direction. + * @retval BT_AUDIO_DIR_SOURCE source direction. + * @retval Negative value Failed to get ep_info from host. + * + */ +int le_audio_stream_dir_get(struct bt_bap_stream const *const stream); + +/** + * @brief Check that the bitrate is within the supported range. + * + * @param[in] codec The audio codec structure. + * + * retval true The bitrate is in the supported range. + * retval false Otherwise. + */ +bool le_audio_bitrate_check(const struct bt_audio_codec_cfg *codec); + +/** + * @brief Check that the sample rate is supported. + * + * @param[in] codec The audio codec structure. + * + * retval true The sample rate is supported. + * retval false Otherwise. + */ +bool le_audio_freq_check(const struct bt_audio_codec_cfg *codec); + +/** + * @brief Print the codec configuration + * + * @param[in] codec Pointer to the audio codec structure. + * @param[in] dir Direction to print the codec configuration for. + */ +void le_audio_print_codec(const struct bt_audio_codec_cfg *codec, enum bt_audio_dir dir); + +#endif /* _LE_AUDIO_H_ */ diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig index 9325705eb84..d354988fe8e 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig @@ -36,6 +36,13 @@ config BT_BAP_UNICAST_24_2_1 help Unicast codec capability 24_2_1. 24kHz, 48kbps, 2 retransmits, 10ms transport latency, and 40ms presentation delay. + +config BT_BAP_UNICAST_48_4_1 + bool "48_4_1" + depends on TRANSPORT_CIS + help + Unicast codec capability 48_4_1. + 48kHz, 96kbps, 5 retransmits, 20ms transport latency, and 40ms presentation delay. endchoice choice BT_AUDIO_PRES_DLY_SRCH @@ -74,6 +81,13 @@ config BT_AUDIO_PRES_DELAY_SRCH_SOURCE then it will revert to the closest supported value. endchoice +config BT_AUDIO_EP_PRINT + bool "Print discovered endpoint capabilities" + default n + help + Print the supported capabilities of an endpoint when it is discovered. + + config CODEC_CAP_COUNT_MAX int "Max storage of codec capabilities" default 5 @@ -115,6 +129,23 @@ config BT_AUDIO_BITRATE_UNICAST_SRC help Bitrate for the unicast source ISO stream. +config BT_SET_IDENTITY_RESOLVING_KEY_DEFAULT + string + default "NRF5340_TWS_DEMO" + help + Default string to configure the Set Identify Resolving Key (SIRK), must + be changed before production uniquely for each coordinated set. + +config BT_SET_IDENTITY_RESOLVING_KEY + string "String used to configure the SIRK" + depends on TRANSPORT_CIS && BT_BAP_UNICAST_SERVER + default BT_SET_IDENTITY_RESOLVING_KEY_DEFAULT + help + Defines a string to configure the Set Identify Resolving Key (SIRK), must + be changed before production uniquely for each coordinated set. The SIRK + must be 16 characters (16 bytes). + + #----------------------------------------------------------------------------# menu "Log levels" diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig.defaults b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig.defaults index d908b8ae347..fd607265d15 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig.defaults +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/Kconfig.defaults @@ -13,6 +13,9 @@ config BT_BONDABLE config BT_PRIVACY default y +config BT_FILTER_ACCEPT_LIST + default y + config BT_SMP default y @@ -32,6 +35,9 @@ config BT_BUF_ACL_RX_SIZE default 502 if (AUDIO_DFU > 0) default 259 +config BT_BUF_ACL_TX_COUNT + default 12 + config SETTINGS default y @@ -49,137 +55,3 @@ config NVS config NVS_LOG_LEVEL default 2 - -# HEADSET -if AUDIO_DEV = 1 - -config BT_BAP_UNICAST_SERVER - default y - -config BT_MAX_CONN - default 1 - -config BT_ISO_MAX_CHAN - default 2 if STREAM_BIDIRECTIONAL - default 1 - -config BT_ASCS_ASE_SNK_COUNT - default 1 - -config BT_ASCS_ASE_SRC_COUNT - default 1 if STREAM_BIDIRECTIONAL - default 0 - -config BT_PERIPHERAL - default y - -config BT_DEVICE_APPEARANCE - # Earbud - 0x0941 - default 2369 - -config BT_GAP_PERIPHERAL_PREF_PARAMS - default n - -config BT_GATT_AUTO_RESUBSCRIBE - default n - -config BT_GATT_AUTO_SEC_REQ - default n - -config BT_VCP_VOL_REND - default y - -config BT_MCC - default n if WALKIE_TALKIE_DEMO - default y - -config BT_PAC_SNK_NOTIFIABLE - # For fixing compatibility issue with Android 14 - default y - -config BT_CSIP_SET_MEMBER - default y - -config BT_CAP_ACCEPTOR - default y - -config BT_CAP_ACCEPTOR_SET_MEMBER - default y - -config BT_AUDIO_TX - default y if STREAM_BIDIRECTIONAL - -config BT_AUDIO_RX - default y - -config BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE - default 25 - -endif # AUDIO_DEV = 1 (HEADSET) - -# GATEWAY -if AUDIO_DEV = 2 - -config BT_BAP_UNICAST_CLIENT - default y - -config BT_ISO_TX_BUF_COUNT - default 2 - -config BT_MAX_CONN - default 2 - -config BT_DEVICE_APPEARANCE - # Generic Audio Source - 0x0880 - default 2176 - -config BT_ISO_MAX_CHAN - default 4 if STREAM_BIDIRECTIONAL - default 2 - -config BT_MAX_PAIRED - default 2 - -config BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT - default 4 if STREAM_BIDIRECTIONAL - default 2 - -config BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT - default 2 - -config BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT - default 2 if STREAM_BIDIRECTIONAL - default 0 - -config BT_VCP_VOL_CTLR - default y - -config BT_MCS - default n if WALKIE_TALKIE_DEMO - default y - -config BT_GATT_DYNAMIC_DB - default y - -config UTF8 - default y - -config BT_MPL - default y - -config MCTL - default y - -config MCTL_LOCAL_PLAYER_CONTROL - default y - -config MCTL_LOCAL_PLAYER_REMOTE_CONTROL - default y - -config BT_AUDIO_TX - default y - -config BT_AUDIO_RX - default y if STREAM_BIDIRECTIONAL - -endif # AUDIO_DEV = 2 (GATEWAY) diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c index 78b75275e4b..3a5622ad3ce 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c @@ -24,6 +24,7 @@ #include "macros_common.h" #include "nrf5340_audio_common.h" +#include "bt_le_audio_tx.h" #include "le_audio.h" #include @@ -32,28 +33,12 @@ LOG_MODULE_REGISTER(unicast_client, CONFIG_UNICAST_CLIENT_LOG_LEVEL); ZBUS_CHAN_DEFINE(le_audio_chan, struct le_audio_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, ZBUS_MSG_INIT(0)); -ZBUS_CHAN_DEFINE(sdu_ref_chan, struct sdu_ref_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, - ZBUS_MSG_INIT(0)); - #define HCI_ISO_BUF_ALLOC_PER_CHAN 2 #define CIS_CONN_RETRY_TIMES 5 #define CIS_CONN_RETRY_DELAY_MS 500 -/* For being able to dynamically define iso_tx_pools */ -#define NET_BUF_POOL_ITERATE(i, _) \ - NET_BUF_POOL_FIXED_DEFINE(iso_tx_pool_##i, HCI_ISO_BUF_ALLOC_PER_CHAN, \ - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); -#define NET_BUF_POOL_PTR_ITERATE(i, ...) IDENTITY(&iso_tx_pool_##i) -LISTIFY(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT, NET_BUF_POOL_ITERATE, (;)) -/* clang-format off */ -static struct net_buf_pool *iso_tx_pools[] = { LISTIFY(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT, - NET_BUF_POOL_PTR_ITERATE, (,)) }; -/* clang-format on */ - struct le_audio_headset { char *ch_name; - bool hci_wrn_printed; - uint32_t seq_num; uint8_t num_sink_eps; uint8_t num_source_eps; struct bt_bap_stream sink_stream; @@ -65,8 +50,6 @@ struct le_audio_headset { struct bt_bap_ep *source_ep; struct bt_audio_codec_cap source_codec_cap[CONFIG_CODEC_CAP_COUNT_MAX]; struct bt_conn *headset_conn; - struct net_buf_pool *iso_tx_pool; - atomic_t iso_tx_pool_alloc; struct k_work_delayable stream_start_sink_work; struct k_work_delayable stream_start_source_work; bool qos_reconfigure; @@ -93,7 +76,6 @@ struct temp_cap_storage { }; static struct le_audio_headset headsets[CONFIG_BT_MAX_CONN]; - static struct discover_dir discover_list[CONFIG_BT_MAX_CONN]; K_MSGQ_DEFINE(kwork_msgq, sizeof(struct worker_data), @@ -115,18 +97,37 @@ static le_audio_receive_cb receive_cb; static struct bt_bap_unicast_group *unicast_group; +/* Used for group creation only */ +static struct bt_bap_lc3_preset lc3_preset_max = BT_BAP_LC3_PRESET_CONFIGURABLE( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_ANY, CONFIG_LC3_BITRATE_MAX); + static struct bt_bap_lc3_preset lc3_preset_sink = BT_BAP_LC3_UNICAST_PRESET_NRF5340_AUDIO_SINK; +static struct bt_bap_lc3_preset lc3_preset_sink_48_4_1 = + BT_BAP_LC3_UNICAST_PRESET_48_4_1(BT_AUDIO_LOCATION_ANY, (BT_AUDIO_CONTEXT_TYPE_ANY)); +static struct bt_bap_lc3_preset lc3_preset_sink_24_2_1 = + BT_BAP_LC3_UNICAST_PRESET_24_2_1(BT_AUDIO_LOCATION_ANY, (BT_AUDIO_CONTEXT_TYPE_ANY)); +static struct bt_bap_lc3_preset lc3_preset_sink_16_2_1 = + BT_BAP_LC3_UNICAST_PRESET_16_2_1(BT_AUDIO_LOCATION_ANY, (BT_AUDIO_CONTEXT_TYPE_ANY)); + static struct bt_bap_lc3_preset lc3_preset_source = BT_BAP_LC3_UNICAST_PRESET_NRF5340_AUDIO_SOURCE; +static struct bt_bap_lc3_preset lc3_preset_source_48_4_1 = + BT_BAP_LC3_UNICAST_PRESET_48_4_1(BT_AUDIO_LOCATION_ANY, BT_AUDIO_CONTEXT_TYPE_ANY); +static struct bt_bap_lc3_preset lc3_preset_source_24_2_1 = + BT_BAP_LC3_UNICAST_PRESET_24_2_1(BT_AUDIO_LOCATION_ANY, BT_AUDIO_CONTEXT_TYPE_ANY); +static struct bt_bap_lc3_preset lc3_preset_source_16_2_1 = + BT_BAP_LC3_UNICAST_PRESET_16_2_1(BT_AUDIO_LOCATION_ANY, BT_AUDIO_CONTEXT_TYPE_ANY); static bool playing_state = true; -static void le_audio_event_publish(enum le_audio_evt_type event, struct bt_conn *conn) +static void le_audio_event_publish(enum le_audio_evt_type event, struct bt_conn *conn, + enum bt_audio_dir dir) { int ret; struct le_audio_msg msg; msg.event = event; msg.conn = conn; + msg.dir = dir; ret = zbus_chan_pub(&le_audio_chan, &msg, LE_AUDIO_ZBUS_EVENT_WAIT_TIME); ERR_CHK(ret); @@ -243,6 +244,9 @@ static int headset_pres_delay_find(uint8_t index, uint32_t *pres_dly_us) uint32_t pref_dly_min = headsets[index].sink_ep->qos_pref.pref_pd_min; uint32_t pref_dly_max = headsets[index].sink_ep->qos_pref.pref_pd_max; + LOG_DBG("Index: %d, Pref min: %d, pref max: %d, pres_min: %d, pres_max: %d", index, + pref_dly_min, pref_dly_max, pres_dly_min, pres_dly_max); + for (int i = 0; i < ARRAY_SIZE(headsets); i++) { if (headsets[i].sink_ep != NULL) { pres_dly_min = MAX(pres_dly_min, headsets[i].sink_ep->qos_pref.pd_min); @@ -265,65 +269,30 @@ static int headset_pres_delay_find(uint8_t index, uint32_t *pres_dly_us) } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_PREF_MIN)) { - *pres_dly_us = pref_dly_min; + /* Preferred min is 0, so we set min supported */ + if (pref_dly_min == 0) { + *pres_dly_us = pres_dly_min; + } else { + *pres_dly_us = pref_dly_min; + } return 0; } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_PREF_MAX)) { - *pres_dly_us = pref_dly_max; - - return 0; - } - - if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_PREF_MIN)) { - if (IN_RANGE(CONFIG_BT_AUDIO_PRESENTATION_DELAY_US, pres_dly_min, pres_dly_max)) { - *pres_dly_us = CONFIG_BT_AUDIO_PRESENTATION_DELAY_US; + /* Preferred max is 0, so we set max supported */ + if (pref_dly_max == 0) { + *pres_dly_us = pres_dly_max; } else { - LOG_WRN("Preferred local presentation delay outside of range"); - - if (pres_dly_max < CONFIG_BT_AUDIO_PRESENTATION_DELAY_US) { - *pres_dly_us = pres_dly_max; - - LOG_WRN("Selecting maximum common delay: %d us ", pres_dly_max); - } else { - *pres_dly_us = pres_dly_min; - - LOG_WRN("Selecting minimum common delay: %d us ", pres_dly_min); - } + *pres_dly_us = pref_dly_max; } return 0; } LOG_ERR("Trying to use unrecognized search mode"); - return -EINVAL; -} -/** - * @brief Check if an endpoint is in the given state. - * - * @note If the endpoint is NULL, it is not in the - * given state, and this function returns false. - * - * @param[in] ep The endpoint to check. - * @param[in] state The state to check for. - * - * @retval true The endpoint is in the given state. - * @retval false Otherwise. - */ -static bool ep_state_check(struct bt_bap_ep *ep, enum bt_bap_ep_state state) -{ - if (ep == NULL) { - /* If an endpoint is NULL it is not in any of the states */ - return false; - } - - if (ep->status.state == state) { - return true; - } - - return false; + return -EINVAL; } /** @@ -354,30 +323,244 @@ static int channel_index_get(const struct bt_conn *conn, uint8_t *index) return -EINVAL; } -static uint32_t get_and_incr_seq_num(const struct bt_bap_stream *stream) +static void supported_sample_rates_print(uint16_t supported_sample_rates, enum bt_audio_dir dir) { - uint8_t channel_index; + char supported_str[20] = ""; - if (channel_index_get(stream->conn, &channel_index) == 0) { - return headsets[channel_index].seq_num++; + if (supported_sample_rates & BT_AUDIO_CODEC_CAP_FREQ_48KHZ) { + strcat(supported_str, "48, "); } - LOG_WRN("Could not find matching stream %p", stream); + if (supported_sample_rates & BT_AUDIO_CODEC_CAP_FREQ_24KHZ) { + strcat(supported_str, "24, "); + } - return 0; + if (supported_sample_rates & BT_AUDIO_CODEC_CAP_FREQ_16KHZ) { + strcat(supported_str, "16, "); + } + + if (dir == BT_AUDIO_DIR_SINK) { + LOG_DBG("Headset supports: %s kHz in sink direction", supported_str); + } else if (dir == BT_AUDIO_DIR_SOURCE) { + LOG_DBG("Headset supports: %s kHz in source direction", supported_str); + } } -static bool parse_cb(struct bt_data *data, void *user_data) +static bool sink_parse_cb(struct bt_data *data, void *user_data) { - if (data->type == BT_AUDIO_CODEC_LC3_FREQ) { - uint16_t temp = sys_get_le16(data->data); + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_FREQ) { + uint16_t lc3_freq_bit = sys_get_le16(data->data); + + supported_sample_rates_print(lc3_freq_bit, BT_AUDIO_DIR_SINK); + + /* Try with the preferred sample rate first */ + switch (CONFIG_BT_AUDIO_PREF_SAMPLE_RATE_VALUE) { + case BT_AUDIO_CODEC_CFG_FREQ_48KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_48KHZ) { + lc3_preset_sink = lc3_preset_sink_48_4_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + break; + + case BT_AUDIO_CODEC_CFG_FREQ_24KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_24KHZ) { + lc3_preset_sink = lc3_preset_sink_24_2_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } - if (temp & BT_AUDIO_CODEC_CAPABILIY_FREQ) { + break; + + case BT_AUDIO_CODEC_CFG_FREQ_16KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_16KHZ) { + lc3_preset_sink = lc3_preset_sink_16_2_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + break; + } + + /* If no match with the preferred, revert to trying highest first */ + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_48KHZ) { + lc3_preset_sink = lc3_preset_sink_48_4_1; + *(bool *)user_data = true; + } else if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_24KHZ) { + lc3_preset_sink = lc3_preset_sink_24_2_1; + *(bool *)user_data = true; + } else if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_16KHZ) { + lc3_preset_sink = lc3_preset_sink_16_2_1; + *(bool *)user_data = true; + } + + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + /* Did not find what we were looking for, continue parsing LTV */ + return true; +} + +static void set_color_if_supported(char *str, uint16_t bitfield, uint16_t mask) +{ + if (bitfield & mask) { + strcat(str, COLOR_GREEN); + } else { + strcat(str, COLOR_RED); + } +} + +static bool caps_print_cb(struct bt_data *data, void *user_data) +{ + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_FREQ) { + uint16_t freq_bit = sys_get_le16(data->data); + char supported_freq[320] = ""; + + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_8KHZ); + strcat(supported_freq, "8, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_11KHZ); + strcat(supported_freq, "11.025, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_16KHZ); + strcat(supported_freq, "16, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_22KHZ); + strcat(supported_freq, "22.05, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_24KHZ); + strcat(supported_freq, "24, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_32KHZ); + strcat(supported_freq, "32, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_44KHZ); + strcat(supported_freq, "44.1, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_48KHZ); + strcat(supported_freq, "48, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_88KHZ); + strcat(supported_freq, "88.2, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_96KHZ); + strcat(supported_freq, "96, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_176KHZ); + strcat(supported_freq, "176, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_192KHZ); + strcat(supported_freq, "192, "); + set_color_if_supported(supported_freq, freq_bit, BT_AUDIO_CODEC_CAP_FREQ_384KHZ); + strcat(supported_freq, "384"); + + LOG_INF("\tFrequencies kHz: %s", supported_freq); + } + + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_DURATION) { + uint16_t dur_bit = sys_get_le16(data->data); + char supported_dur[30] = ""; + + set_color_if_supported(supported_dur, dur_bit, BT_AUDIO_CODEC_CAP_DURATION_7_5); + strcat(supported_dur, "7.5, "); + set_color_if_supported(supported_dur, dur_bit, BT_AUDIO_CODEC_CAP_DURATION_10); + strcat(supported_dur, "10"); + + LOG_INF("\tFrame duration ms: %s", supported_dur); + } + + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT) { + uint16_t chan_bit = sys_get_le16(data->data); + char supported_chan[120] = ""; + + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_1); + strcat(supported_chan, "1, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_2); + strcat(supported_chan, "2, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_3); + strcat(supported_chan, "3, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_4); + strcat(supported_chan, "4, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_5); + strcat(supported_chan, "5, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_6); + strcat(supported_chan, "6, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_7); + strcat(supported_chan, "7, "); + set_color_if_supported(supported_chan, chan_bit, BT_AUDIO_CODEC_CAP_CHAN_COUNT_8); + strcat(supported_chan, "8"); + + LOG_INF("\tChannels supported: %s", supported_chan); + } + + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_FRAME_LEN) { + uint16_t lc3_min_frame_length = sys_get_le16(data->data); + uint16_t lc3_max_frame_length = sys_get_le16(data->data + sizeof(uint16_t)); + + LOG_INF("\tFrame length bytes: %d - %d", lc3_min_frame_length, + lc3_max_frame_length); + } + + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_FRAME_COUNT) { + uint16_t lc3_frame_per_sdu = sys_get_le16(data->data); + + LOG_INF("\tMax frames per SDU: %d", lc3_frame_per_sdu); + } + + return true; +} + +static bool source_parse_cb(struct bt_data *data, void *user_data) +{ + if (data->type == BT_AUDIO_CODEC_CAP_TYPE_FREQ) { + uint16_t lc3_freq_bit = sys_get_le16(data->data); + + supported_sample_rates_print(lc3_freq_bit, BT_AUDIO_DIR_SOURCE); + + /* Try with the preferred sample rate first */ + switch (CONFIG_BT_AUDIO_PREF_SAMPLE_RATE_VALUE) { + case BT_AUDIO_CODEC_CFG_FREQ_48KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_48KHZ) { + lc3_preset_source = lc3_preset_source_48_4_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + break; + + case BT_AUDIO_CODEC_CFG_FREQ_24KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_24KHZ) { + lc3_preset_source = lc3_preset_source_24_2_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + break; + + case BT_AUDIO_CODEC_CFG_FREQ_16KHZ: + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_16KHZ) { + lc3_preset_source = lc3_preset_source_16_2_1; + *(bool *)user_data = true; + /* Found what we were looking for, stop parsing LTV */ + return false; + } + + break; + } + + /* If no match with the preferred, revert to trying highest first */ + if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_48KHZ) { + lc3_preset_source = lc3_preset_source_48_4_1; + *(bool *)user_data = true; + } else if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_24KHZ) { + lc3_preset_source = lc3_preset_source_24_2_1; + *(bool *)user_data = true; + } else if (lc3_freq_bit & BT_AUDIO_CODEC_CAP_FREQ_16KHZ) { + lc3_preset_source = lc3_preset_source_16_2_1; *(bool *)user_data = true; } + + /* Found what we were looking for, stop parsing LTV */ return false; } + /* Did not find what we were looking for, continue parsing LTV */ return true; } @@ -386,19 +569,47 @@ static bool parse_cb(struct bt_data *data, void *user_data) * * @note Currently only the sampling frequency is checked. * - * @param cap_array The array of pointers to codec capabilities. - * @param num_caps The size of cap_array. + * @param[in] cap_array The array of pointers to codec capabilities. + * @param[in] num_caps The size of cap_array. + * @param[in] dir Direction of the capabilities to check. + * @param[in] index Channel index. * * @return True if valid codec capability found, false otherwise. */ -static bool valid_codec_cap_check(struct bt_audio_codec_cap cap_array[], uint8_t num_caps) +static bool valid_codec_cap_check(struct bt_audio_codec_cap cap_array[], uint8_t num_caps, + enum bt_audio_dir dir, uint8_t index) { bool valid_result = false; /* Only the sampling frequency is checked */ - for (int i = 0; i < num_caps; i++) { - (void)bt_audio_data_parse(cap_array[i].data, cap_array[i].data_len, parse_cb, - &valid_result); + if (dir == BT_AUDIO_DIR_SINK) { + LOG_INF("Discovered %d sink endpoint(s) for device %d", num_caps, index); + for (int i = 0; i < num_caps; i++) { + if (IS_ENABLED(CONFIG_BT_AUDIO_EP_PRINT)) { + LOG_INF(""); + LOG_INF("Dev: %d Sink EP %d", index, i); + (void)bt_audio_data_parse(cap_array[i].data, cap_array[i].data_len, + caps_print_cb, NULL); + LOG_INF("__________________________"); + } + + (void)bt_audio_data_parse(cap_array[i].data, cap_array[i].data_len, + sink_parse_cb, &valid_result); + } + } else if (dir == BT_AUDIO_DIR_SOURCE) { + LOG_INF("Discovered %d source endpoint(s) for device %d", num_caps, index); + for (int i = 0; i < num_caps; i++) { + if (IS_ENABLED(CONFIG_BT_AUDIO_EP_PRINT)) { + LOG_INF(""); + LOG_INF("Dev: %d Source EP %d", index, i); + (void)bt_audio_data_parse(cap_array[i].data, cap_array[i].data_len, + caps_print_cb, NULL); + LOG_INF("__________________________"); + } + + (void)bt_audio_data_parse(cap_array[i].data, cap_array[i].data_len, + source_parse_cb, &valid_result); + } } return valid_result; @@ -420,7 +631,7 @@ static void bt_audio_codec_allocation_set(struct bt_audio_codec_cfg *codec_cfg, uint8_t *value = &codec_cfg->data[i]; const uint8_t value_len = len - sizeof(type); - if (type == BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC) { + if (type == BT_AUDIO_CODEC_CFG_CHAN_ALLOC) { const uint32_t loc_32 = loc; sys_put_le32(loc_32, value); @@ -446,7 +657,7 @@ static int update_sink_stream_qos(struct le_audio_headset *headset, uint32_t pre if (headset->sink_stream.qos->pd != pres_delay_us) { if (playing_state && - ep_state_check(headset->sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { + le_audio_ep_state_check(headset->sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { LOG_DBG("Update streaming %s headset, connection %p, stream %p", headset->ch_name, &headset->headset_conn, &headset->sink_stream); @@ -504,7 +715,7 @@ static void unicast_client_location_cb(struct bt_conn *conn, enum bt_audio_dir d } } else { LOG_WRN("Channel location not supported"); - le_audio_event_publish(LE_AUDIO_EVT_NO_VALID_CFG, conn); + le_audio_event_publish(LE_AUDIO_EVT_NO_VALID_CFG, conn, dir); } } @@ -515,7 +726,7 @@ static void available_contexts_cb(struct bt_conn *conn, enum bt_audio_context sn (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - LOG_DBG("conn: %s, snk ctx %d src ctx %d\n", addr, snk_ctx, src_ctx); + LOG_DBG("conn: %s, snk ctx %d src ctx %d", addr, snk_ctx, src_ctx); } static int temp_cap_index_get(struct bt_conn *conn, uint8_t *index) @@ -590,8 +801,8 @@ static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_b if (dir == BT_AUDIO_DIR_SINK) { if (ep != NULL) { if (headsets[channel_index].num_sink_eps > 0) { - LOG_WRN("More than one sink endpoint found, idx 0 is used by " - "default"); + LOG_WRN("More than one sink endpoint found, idx 0 is used " + "by default"); return; } @@ -608,8 +819,8 @@ static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_b } else if (dir == BT_AUDIO_DIR_SOURCE) { if (ep != NULL) { if (headsets[channel_index].num_source_eps > 0) { - LOG_WRN("More than one source endpoint found, idx 0 is used by " - "default"); + LOG_WRN("More than one source endpoint found, idx 0 is " + "used by default"); return; } @@ -648,9 +859,9 @@ static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) LOG_WRN("No sources found"); headsets[channel_index].waiting_for_source_disc = false; /** - * We usually wait until both sink and source has been discovered before - * configuring, but since no source was found and we have a sink, we need - * to configure that. + * We usually wait until both sink and source has been discovered + * before configuring, but since no source was found and we have a + * sink, we need to configure that. */ if (headsets[channel_index].sink_ep != NULL) { ret = bt_bap_stream_config(conn, @@ -689,7 +900,8 @@ static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) if (dir == BT_AUDIO_DIR_SINK) { if (valid_codec_cap_check(headsets[channel_index].sink_codec_cap, - temp_cap[temp_cap_index].num_caps)) { + temp_cap[temp_cap_index].num_caps, BT_AUDIO_DIR_SINK, + channel_index)) { if (conn == headsets[AUDIO_CH_L].headset_conn) { bt_audio_codec_allocation_set(&lc3_preset_sink.codec_cfg, BT_AUDIO_LOCATION_FRONT_LEFT); @@ -707,7 +919,8 @@ static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) } } else if (dir == BT_AUDIO_DIR_SOURCE) { if (valid_codec_cap_check(headsets[channel_index].source_codec_cap, - temp_cap[temp_cap_index].num_caps)) { + temp_cap[temp_cap_index].num_caps, BT_AUDIO_DIR_SOURCE, + channel_index)) { if (conn == headsets[AUDIO_CH_L].headset_conn) { bt_audio_codec_allocation_set(&lc3_preset_source.codec_cfg, BT_AUDIO_LOCATION_FRONT_LEFT); @@ -776,11 +989,16 @@ static void stream_sent_cb(struct bt_bap_stream *stream) int ret; uint8_t channel_index; - ret = channel_index_get(stream->conn, &channel_index); - if (ret) { - LOG_ERR("Channel index not found"); + if (le_audio_ep_state_check(stream->ep, BT_BAP_EP_STATE_STREAMING)) { + + ret = channel_index_get(stream->conn, &channel_index); + if (ret) { + LOG_ERR("Channel index not found"); + } else { + ERR_CHK(bt_le_audio_tx_stream_sent(channel_index)); + } } else { - atomic_dec(&headsets[channel_index].iso_tx_pool_alloc); + LOG_WRN("Not in streaming state"); } } @@ -800,12 +1018,18 @@ static void stream_configured_cb(struct bt_bap_stream *stream, if (stream->ep->dir == BT_AUDIO_DIR_SINK) { /* NOTE: The string below is used by the Nordic CI system */ LOG_INF("%s sink stream configured", headsets[channel_index].ch_name); + le_audio_print_codec(headsets[channel_index].sink_stream.codec_cfg, + stream->ep->dir); } else if (stream->ep->dir == BT_AUDIO_DIR_SOURCE) { LOG_INF("%s source stream configured", headsets[channel_index].ch_name); + le_audio_print_codec(headsets[channel_index].source_stream.codec_cfg, + stream->ep->dir); } else { LOG_WRN("Endpoint direction not recognized: %d", stream->ep->dir); return; } + LOG_DBG("Configured Stream info: %s, %p, dir %d", headsets[channel_index].ch_name, + (void *)stream, stream->ep->dir); ret = headset_pres_delay_find(channel_index, &new_pres_dly_us); if (ret) { @@ -817,8 +1041,8 @@ static void stream_configured_cb(struct bt_bap_stream *stream, return; } - if (ep_state_check(headsets[channel_index].sink_stream.ep, - BT_BAP_EP_STATE_CODEC_CONFIGURED)) { + if (le_audio_ep_state_check(headsets[channel_index].sink_stream.ep, + BT_BAP_EP_STATE_CODEC_CONFIGURED)) { for (int i = 0; i < ARRAY_SIZE(headsets); i++) { if (i != channel_index && headsets[i].headset_conn != NULL) { ret = update_sink_stream_qos(&headsets[i], new_pres_dly_us); @@ -837,13 +1061,17 @@ static void stream_configured_cb(struct bt_bap_stream *stream, headsets[channel_index].sink_stream.qos->pd = new_pres_dly_us; } - /* Make sure both sink and source ep (if both are discovered) are configured before QoS */ + le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED, stream->conn, stream->ep->dir); + + /* Make sure both sink and source ep (if both are discovered) are configured before + * QoS + */ if ((headsets[channel_index].sink_ep != NULL && - !ep_state_check(headsets[channel_index].sink_stream.ep, - BT_BAP_EP_STATE_CODEC_CONFIGURED)) || + !le_audio_ep_state_check(headsets[channel_index].sink_stream.ep, + BT_BAP_EP_STATE_CODEC_CONFIGURED)) || (headsets[channel_index].source_ep != NULL && - !ep_state_check(headsets[channel_index].source_stream.ep, - BT_BAP_EP_STATE_CODEC_CONFIGURED))) { + !le_audio_ep_state_check(headsets[channel_index].source_stream.ep, + BT_BAP_EP_STATE_CODEC_CONFIGURED))) { return; } @@ -894,6 +1122,13 @@ static void stream_enabled_cb(struct bt_bap_stream *stream) int ret; uint8_t channel_index; struct worker_data work_data; + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return; + } LOG_DBG("Stream enabled: %p", stream); @@ -903,8 +1138,9 @@ static void stream_enabled_cb(struct bt_bap_stream *stream) return; } - if (stream->ep->dir == BT_AUDIO_DIR_SINK && - ep_state_check(headsets[channel_index].sink_stream.ep, BT_BAP_EP_STATE_ENABLING)) { + if (dir == BT_AUDIO_DIR_SINK && + le_audio_ep_state_check(headsets[channel_index].sink_stream.ep, + BT_BAP_EP_STATE_ENABLING)) { if (!k_work_delayable_is_pending(&headsets[channel_index].stream_start_sink_work)) { work_data.channel_index = channel_index; work_data.retries = 0; @@ -923,8 +1159,9 @@ static void stream_enabled_cb(struct bt_bap_stream *stream) } } - if (stream->ep->dir == BT_AUDIO_DIR_SOURCE && - ep_state_check(headsets[channel_index].source_stream.ep, BT_BAP_EP_STATE_ENABLING)) { + if (dir == BT_AUDIO_DIR_SOURCE && + le_audio_ep_state_check(headsets[channel_index].source_stream.ep, + BT_BAP_EP_STATE_ENABLING)) { if (!k_work_delayable_is_pending( &headsets[channel_index].stream_start_source_work)) { work_data.channel_index = channel_index; @@ -948,17 +1185,27 @@ static void stream_enabled_cb(struct bt_bap_stream *stream) static void stream_started_cb(struct bt_bap_stream *stream) { + int ret; uint8_t channel_index; + enum bt_audio_dir dir; - /* Reset sequence number for the stream */ - if (channel_index_get(stream->conn, &channel_index) == 0) { - headsets[channel_index].seq_num = 0; + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return; + } + + ret = channel_index_get(stream->conn, &channel_index); + if (ret) { + LOG_ERR("Channel index not found"); + } else { + ERR_CHK(bt_le_audio_tx_stream_started(channel_index)); } /* NOTE: The string below is used by the Nordic CI system */ LOG_INF("Stream %p started", (void *)stream); - le_audio_event_publish(LE_AUDIO_EVT_STREAMING, stream->conn); + le_audio_event_publish(LE_AUDIO_EVT_STREAMING, stream->conn, dir); } static void stream_metadata_updated_cb(struct bt_bap_stream *stream) @@ -983,20 +1230,21 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) if (ret) { LOG_ERR("Channel index not found"); } else { - atomic_clear(&headsets[channel_index].iso_tx_pool_alloc); - headsets[channel_index].hci_wrn_printed = false; + ERR_CHK(bt_le_audio_tx_stream_stopped(channel_index)); } /* Check if the other stream is streaming, send event if not */ if (stream == &headsets[AUDIO_CH_L].sink_stream) { - if (!ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + if (!le_audio_ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, + BT_AUDIO_DIR_SINK); } } else if (stream == &headsets[AUDIO_CH_R].sink_stream) { - if (!ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + if (!le_audio_ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, + BT_AUDIO_DIR_SINK); } } else { LOG_WRN("Unknown stream"); @@ -1009,16 +1257,18 @@ static void stream_released_cb(struct bt_bap_stream *stream) /* Check if the other stream is streaming, send event if not */ if (stream == &headsets[AUDIO_CH_L].sink_stream) { - if (!ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + if (!le_audio_ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, + BT_AUDIO_DIR_SINK); } LOG_DBG("Left sink stream released"); } else if (stream == &headsets[AUDIO_CH_R].sink_stream) { - if (!ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + if (!le_audio_ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, + BT_AUDIO_DIR_SINK); } LOG_DBG("Right sink stream released"); @@ -1091,19 +1341,20 @@ static void work_stream_start(struct k_work *work) work_data.retries); if (work_data.dir == BT_AUDIO_DIR_SINK) { - if (!ep_state_check(headsets[work_data.channel_index].sink_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { + if (!le_audio_ep_state_check(headsets[work_data.channel_index].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { ret = bt_bap_stream_start(&headsets[work_data.channel_index].sink_stream); } } else if (work_data.dir == BT_AUDIO_DIR_SOURCE) { - if (!ep_state_check(headsets[work_data.channel_index].source_stream.ep, - BT_BAP_EP_STATE_STREAMING)) { + if (!le_audio_ep_state_check(headsets[work_data.channel_index].source_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { ret = bt_bap_stream_start(&headsets[work_data.channel_index].source_stream); } } else { - LOG_ERR("Trying to use unknown direction"); + LOG_ERR("Trying to use unknown direction: %d", work_data.dir); le_audio_event_publish(LE_AUDIO_EVT_NO_VALID_CFG, - headsets[work_data.channel_index].headset_conn); + headsets[work_data.channel_index].headset_conn, + work_data.dir); return; } @@ -1130,12 +1381,28 @@ static void work_stream_start(struct k_work *work) K_MSEC(CIS_CONN_RETRY_DELAY_MS)); } } else if (ret != 0) { - LOG_ERR("Failed to establish CIS, ret = %d", ret); - /** Defining the connection as having invalid configs, since it is not - * possible to start stream + LOG_WRN("Failed to establish CIS, ret = %d", ret); + /** The connection could have invalid configs, or abnormal behavior cause + * the CIS failed to establish. Sending an event for triggering + * disconnection could clean up the abnormal state and restart the + * connection. */ le_audio_event_publish(LE_AUDIO_EVT_NO_VALID_CFG, - headsets[work_data.channel_index].headset_conn); + headsets[work_data.channel_index].headset_conn, + work_data.dir); + } else if (k_msgq_peek(&kwork_msgq, &work_data) != -ENOMSG) { + if (work_data.dir == BT_AUDIO_DIR_SINK && + !k_work_delayable_is_pending( + &headsets[work_data.channel_index].stream_start_sink_work)) { + k_work_reschedule(&headsets[work_data.channel_index].stream_start_sink_work, + K_MSEC(CIS_CONN_RETRY_DELAY_MS)); + } else if (work_data.dir == BT_AUDIO_DIR_SOURCE && + !k_work_delayable_is_pending( + &headsets[work_data.channel_index].stream_start_source_work)) { + k_work_reschedule( + &headsets[work_data.channel_index].stream_start_source_work, + K_MSEC(CIS_CONN_RETRY_DELAY_MS)); + } } } @@ -1153,49 +1420,75 @@ static void disconnected_headset_cleanup(uint8_t chan_idx) headsets[chan_idx].num_source_eps = 0; } -static int iso_stream_send(uint8_t const *const data, size_t size, struct le_audio_headset *headset) +int unicast_client_config_get(struct bt_conn *conn, enum bt_audio_dir dir, uint32_t *bitrate, + uint32_t *sampling_rate_hz) { int ret; - struct net_buf *buf; - - /* net_buf_alloc allocates buffers for APP->NET transfer over HCI RPMsg, - * but when these buffers are released it is not guaranteed that the - * data has actually been sent. The data might be queued on the NET core, - * and this can cause delays in the audio. - * When stream_sent_cb() is called the data has been sent. - * Data will be discarded if allocation becomes too high, to avoid audio delays. - * If the NET and APP core operates in clock sync, discarding should not occur. - */ - if (atomic_get(&headset->iso_tx_pool_alloc) >= HCI_ISO_BUF_ALLOC_PER_CHAN) { - if (!headset->hci_wrn_printed) { - LOG_WRN("HCI ISO TX overrun on %s ch - Single print", headset->ch_name); - headset->hci_wrn_printed = true; - } + uint8_t headset_idx; - return -ENOMEM; + if (conn == NULL) { + LOG_ERR("No valid connection pointer received"); + return -EINVAL; } - headset->hci_wrn_printed = false; + if (bitrate == NULL && sampling_rate_hz == NULL) { + LOG_ERR("No valid pointers received"); + return -ENXIO; + } - buf = net_buf_alloc(headset->iso_tx_pool, K_NO_WAIT); - if (buf == NULL) { - /* This should never occur because of the iso_tx_pool_alloc check above */ - LOG_WRN("Out of TX buffers"); - return -ENOMEM; + ret = channel_index_get(conn, &headset_idx); + if (ret) { + LOG_WRN("No configured streams found"); + return ret; } - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buf_add_mem(buf, data, size); + if (dir == BT_AUDIO_DIR_SINK) { + if (headsets[headset_idx].sink_stream.codec_cfg == NULL) { + LOG_ERR("No codec found for the stream"); + + return -ENXIO; + } + + if (sampling_rate_hz != NULL) { + ret = le_audio_freq_hz_get(headsets[headset_idx].sink_stream.codec_cfg, + sampling_rate_hz); + if (ret) { + LOG_ERR("Invalid sampling frequency: %d", ret); + return -ENXIO; + } + } + + if (bitrate != NULL) { + ret = le_audio_bitrate_get(headsets[headset_idx].sink_stream.codec_cfg, + bitrate); + if (ret) { + LOG_ERR("Unable to calculate bitrate: %d", ret); + return -ENXIO; + } + } + } else if (dir == BT_AUDIO_DIR_SOURCE) { + if (headsets[headset_idx].source_stream.codec_cfg == NULL) { + LOG_ERR("No codec found for the stream"); + return -ENXIO; + } - atomic_inc(&headset->iso_tx_pool_alloc); + if (sampling_rate_hz != NULL) { + ret = le_audio_freq_hz_get(headsets[headset_idx].source_stream.codec_cfg, + sampling_rate_hz); + if (ret) { + LOG_ERR("Invalid sampling frequency: %d", ret); + return -ENXIO; + } + } - ret = bt_bap_stream_send(&headset->sink_stream, buf, - get_and_incr_seq_num(&headset->sink_stream), - BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - LOG_WRN("Failed to send audio data to %s: %d", headset->ch_name, ret); - net_buf_unref(buf); - atomic_dec(&headset->iso_tx_pool_alloc); + if (bitrate != NULL) { + ret = le_audio_bitrate_get(headsets[headset_idx].source_stream.codec_cfg, + bitrate); + if (ret) { + LOG_ERR("Unable to calculate bitrate: %d", ret); + return -ENXIO; + } + } } return 0; @@ -1245,7 +1538,8 @@ int unicast_client_start(void) int ret_left = 0; int ret_right = 0; - if (ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, BT_BAP_EP_STATE_QOS_CONFIGURED)) { + if (le_audio_ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, + BT_BAP_EP_STATE_QOS_CONFIGURED)) { ret_left = bt_bap_stream_enable(&headsets[AUDIO_CH_L].sink_stream, lc3_preset_sink.codec_cfg.meta, lc3_preset_sink.codec_cfg.meta_len); @@ -1255,7 +1549,8 @@ int unicast_client_start(void) } } - if (ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, BT_BAP_EP_STATE_QOS_CONFIGURED)) { + if (le_audio_ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, + BT_BAP_EP_STATE_QOS_CONFIGURED)) { ret_right = bt_bap_stream_enable(&headsets[AUDIO_CH_R].sink_stream, lc3_preset_sink.codec_cfg.meta, lc3_preset_sink.codec_cfg.meta_len); @@ -1279,9 +1574,10 @@ int unicast_client_stop(void) int ret_left = 0; int ret_right = 0; - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, NULL); + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, NULL, 0); - if (ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { + if (le_audio_ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { ret_left = bt_bap_stream_disable(&headsets[AUDIO_CH_L].sink_stream); if (ret_left) { @@ -1289,7 +1585,8 @@ int unicast_client_stop(void) } } - if (ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { + if (le_audio_ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, + BT_BAP_EP_STATE_STREAMING)) { ret_right = bt_bap_stream_disable(&headsets[AUDIO_CH_R].sink_stream); if (ret_right) { @@ -1309,71 +1606,19 @@ int unicast_client_stop(void) int unicast_client_send(struct le_audio_encoded_audio enc_audio) { int ret; - size_t data_size_pr_stream; - struct bt_iso_tx_info tx_info = {0}; - struct sdu_ref_msg msg; - - if ((enc_audio.num_ch == 1) || (enc_audio.num_ch == ARRAY_SIZE(headsets))) { - data_size_pr_stream = enc_audio.size / enc_audio.num_ch; - } else { - LOG_ERR("Num encoded channels must be 1 or equal to num headsets"); - return -EINVAL; - } - - if (data_size_pr_stream != LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_BT_AUDIO_BITRATE_UNICAST_SINK)) { - LOG_ERR("The encoded data size does not match the SDU size"); - return -EINVAL; - } +#if CONFIG_BT_AUDIO_TX + struct bt_bap_stream *bap_tx_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; - if (ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { - ret = bt_iso_chan_get_tx_sync(&headsets[AUDIO_CH_L].sink_stream.ep->iso->chan, - &tx_info); - } else if (ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { - ret = bt_iso_chan_get_tx_sync(&headsets[AUDIO_CH_R].sink_stream.ep->iso->chan, - &tx_info); - } else { - /* This can happen if a headset is reset and the state in - * streamctrl hasn't had time to update yet - */ - LOG_DBG("No headset in stream state"); - return -ECANCELED; + for (int i = 0; i < CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT; i++) { + bap_tx_streams[i] = &headsets[i].sink_stream; } + ret = bt_le_audio_tx_send(bap_tx_streams, enc_audio, + CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT); if (ret) { - LOG_DBG("Error getting ISO TX anchor point: %d", ret); - } - - if (tx_info.ts != 0 && !ret) { - if (!IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL)) { - msg.timestamp = tx_info.ts; - msg.adjust = true; - - ret = zbus_chan_pub(&sdu_ref_chan, &msg, K_NO_WAIT); - if (ret) { - LOG_WRN("Failed to publish timestamp: %d", ret); - } - } - } - - if (ep_state_check(headsets[AUDIO_CH_L].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { - ret = iso_stream_send(enc_audio.data, data_size_pr_stream, &headsets[AUDIO_CH_L]); - if (ret) { - LOG_DBG("Failed to send data to left channel"); - } - } - - if (ep_state_check(headsets[AUDIO_CH_R].sink_stream.ep, BT_BAP_EP_STATE_STREAMING)) { - if (enc_audio.num_ch == 1) { - ret = iso_stream_send(enc_audio.data, data_size_pr_stream, - &headsets[AUDIO_CH_R]); - } else { - ret = iso_stream_send(&enc_audio.data[data_size_pr_stream], - data_size_pr_stream, &headsets[AUDIO_CH_R]); - } - if (ret) { - LOG_DBG("Failed to send data to right channel"); - } + return ret; } +#endif /*CONFIG_BT_AUDIO_TX*/ return 0; } @@ -1421,8 +1666,12 @@ int unicast_client_enable(le_audio_receive_cb recv_cb) return ret; } + ret = bt_le_audio_tx_init(); + if (ret) { + return ret; + } + for (int i = 0; i < ARRAY_SIZE(headsets); i++) { - headsets[i].iso_tx_pool = iso_tx_pools[i]; switch (i) { case AUDIO_CH_L: headsets[i].ch_name = "LEFT"; @@ -1440,10 +1689,10 @@ int unicast_client_enable(le_audio_receive_cb recv_cb) for (int i = 0; i < ARRAY_SIZE(group_stream_params); i++) { /* Every other stream should be sink or source */ if ((i % 2) == 0) { - group_stream_params[i].qos = &lc3_preset_sink.qos; + group_stream_params[i].qos = &lc3_preset_max.qos; group_stream_params[i].stream = &headsets[headset_iterator].sink_stream; } else { - group_stream_params[i].qos = &lc3_preset_source.qos; + group_stream_params[i].qos = &lc3_preset_max.qos; group_stream_params[i].stream = &headsets[headset_iterator].source_stream; headset_iterator++; } diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.h index 785453c9184..7b64e0d77e7 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.h @@ -7,7 +7,7 @@ #ifndef _UNICAST_CLIENT_H_ #define _UNICAST_CLIENT_H_ -#include "le_audio.h" +#include "bt_le_audio_tx.h" #include #include @@ -40,10 +40,29 @@ enum unicast_discover_dir { #define BT_BAP_LC3_UNICAST_PRESET_NRF5340_AUDIO_SOURCE \ BT_BAP_LC3_UNICAST_PRESET_24_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_MEDIA) +#elif CONFIG_BT_BAP_UNICAST_48_4_1 +#define BT_BAP_LC3_UNICAST_PRESET_NRF5340_AUDIO_SINK \ + BT_BAP_LC3_UNICAST_PRESET_48_4_1(BT_AUDIO_LOCATION_ANY, BT_AUDIO_CONTEXT_TYPE_MEDIA) + +#define BT_BAP_LC3_UNICAST_PRESET_NRF5340_AUDIO_SOURCE \ + BT_BAP_LC3_UNICAST_PRESET_48_4_1(BT_AUDIO_LOCATION_ANY, BT_AUDIO_CONTEXT_TYPE_MEDIA) #else #error Unsupported LC3 codec preset for unicast #endif /* CONFIG_BT_BAP_UNICAST_CONFIGURABLE */ +/** + * @brief Get configuration for the audio stream. + * + * @param[in] conn Pointer to the connection to get the configuration for. + * @param[in] dir Direction to get the configuration from. + * @param[out] bitrate Pointer to the bit rate used; can be NULL. + * @param[out] sampling_rate_hz Pointer to the sampling rate used; can be NULL. + * + * @return 0 for success, error otherwise. + */ +int unicast_client_config_get(struct bt_conn *conn, enum bt_audio_dir dir, uint32_t *bitrate, + uint32_t *sampling_rate_hz); + /** * @brief Start service discovery for a Bluetooth LE Audio unicast (CIS) server. * diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.c index ce0276d4f3c..3dab41b4f0c 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.c @@ -15,12 +15,13 @@ #include #include -/* TODO: Remove when a get_info function is implemented in host */ -#include <../subsys/bluetooth/audio/bap_endpoint.h> - #include "macros_common.h" #include "nrf5340_audio_common.h" #include "channel_assignment.h" +#include "bt_le_audio_tx.h" +#include "le_audio.h" + +#include <../subsys/bluetooth/audio/bap_endpoint.h> #include LOG_MODULE_REGISTER(unicast_server, CONFIG_UNICAST_SERVER_LOG_LEVEL); @@ -28,28 +29,14 @@ LOG_MODULE_REGISTER(unicast_server, CONFIG_UNICAST_SERVER_LOG_LEVEL); BUILD_ASSERT(CONFIG_BT_ASCS_ASE_SRC_COUNT <= 1, "A maximum of one source stream is currently supported"); +BUILD_ASSERT(strlen(CONFIG_BT_SET_IDENTITY_RESOLVING_KEY) == BT_CSIP_SET_SIRK_SIZE, + "SIRK incorrect size, must be 16 bytes"); + ZBUS_CHAN_DEFINE(le_audio_chan, struct le_audio_msg, NULL, NULL, ZBUS_OBSERVERS_EMPTY, ZBUS_MSG_INIT(0)); #define BLE_ISO_LATENCY_MS 10 - -#if (CONFIG_BT_AUDIO_TX) -#define HCI_ISO_BUF_ALLOC_PER_CHAN 2 -/* For being able to dynamically define iso_tx_pools */ -#define NET_BUF_POOL_ITERATE(i, _) \ - NET_BUF_POOL_FIXED_DEFINE(iso_tx_pool_##i, HCI_ISO_BUF_ALLOC_PER_CHAN, \ - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); -#define NET_BUF_POOL_PTR_ITERATE(i, ...) IDENTITY(&iso_tx_pool_##i) -LISTIFY(CONFIG_BT_ASCS_ASE_SRC_COUNT, NET_BUF_POOL_ITERATE, (;)) - -static atomic_t iso_tx_pool_alloc; -/* clang-format off */ -static struct net_buf_pool *iso_tx_pools[] = { LISTIFY(CONFIG_BT_ASCS_ASE_SRC_COUNT, - NET_BUF_POOL_PTR_ITERATE, (,)) }; -/* clang-format on */ -#endif /* (CONFIG_BT_AUDIO_TX) */ - -#define CSIP_SET_SIZE 2 +#define CSIP_SET_SIZE 2 enum csip_set_rank { CSIP_HL_RANK = 1, CSIP_HR_RANK = 2 @@ -73,16 +60,14 @@ static const uint8_t cap_adv_data[] = { }; #if defined(CONFIG_BT_AUDIO_RX) -#define AVAILABLE_SINK_CONTEXT \ - (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_MEDIA | \ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL) +#define AVAILABLE_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_ANY) #else #define AVAILABLE_SINK_CONTEXT BT_AUDIO_CONTEXT_TYPE_PROHIBITED #endif /* CONFIG_BT_AUDIO_RX */ +static struct bt_bap_stream *bap_tx_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; #if defined(CONFIG_BT_AUDIO_TX) -#define AVAILABLE_SOURCE_CONTEXT \ - (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL) +#define AVAILABLE_SOURCE_CONTEXT (BT_AUDIO_CONTEXT_TYPE_ANY) #else #define AVAILABLE_SOURCE_CONTEXT BT_AUDIO_CONTEXT_TYPE_PROHIBITED #endif /* CONFIG_BT_AUDIO_TX */ @@ -95,13 +80,15 @@ static uint8_t unicast_server_adv_data[] = { 0x00, /* Metadata length */ }; -static void le_audio_event_publish(enum le_audio_evt_type event, struct bt_conn *conn) +static void le_audio_event_publish(enum le_audio_evt_type event, struct bt_conn *conn, + enum bt_audio_dir dir) { int ret; struct le_audio_msg msg; msg.event = event; msg.conn = conn; + msg.dir = dir; ret = zbus_chan_pub(&le_audio_chan, &msg, LE_AUDIO_ZBUS_EVENT_WAIT_TIME); ERR_CHK(ret); @@ -128,25 +115,26 @@ static struct bt_csip_set_member_cb csip_callbacks = { struct bt_csip_set_member_register_param csip_param = { .set_size = CSIP_SET_SIZE, .lockable = true, -#if !CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA - /* CSIP SIRK for demo is used, must be changed before production */ - .set_sirk = {'N', 'R', 'F', '5', '3', '4', '0', '_', 'T', 'W', 'S', '_', 'D', 'E', 'M', - 'O'}, -#else -#warning "CSIP test sample data is used, must be changed before production" -#endif .cb = &csip_callbacks, }; -static struct bt_audio_codec_cap lc3_codec = BT_AUDIO_CODEC_CAP_LC3( +static struct bt_audio_codec_cap lc3_codec_sink = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_CAPABILIY_FREQ, + (BT_AUDIO_CODEC_CAP_DURATION_10 | BT_AUDIO_CODEC_CAP_DURATION_PREFER_10), + BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN), + LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, AVAILABLE_SINK_CONTEXT); + +#if defined(CONFIG_BT_AUDIO_TX) +static struct bt_audio_codec_cap lc3_codec_source = BT_AUDIO_CODEC_CAP_LC3( BT_AUDIO_CODEC_CAPABILIY_FREQ, - (BT_AUDIO_CODEC_LC3_DURATION_10 | BT_AUDIO_CODEC_LC3_DURATION_PREFER_10), - BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN), - LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, BT_AUDIO_CONTEXT_TYPE_MEDIA); + (BT_AUDIO_CODEC_CAP_DURATION_10 | BT_AUDIO_CODEC_CAP_DURATION_PREFER_10), + BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN), + LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, AVAILABLE_SOURCE_CONTEXT); +#endif /* (CONFIG_BT_AUDIO_TX) */ static enum bt_audio_dir caps_dirs[] = { BT_AUDIO_DIR_SINK, -#if (CONFIG_BT_AUDIO_TX) +#if defined(CONFIG_BT_AUDIO_TX) BT_AUDIO_DIR_SOURCE, #endif /* (CONFIG_BT_AUDIO_TX) */ }; @@ -160,12 +148,12 @@ static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF( static struct bt_pacs_cap caps[] = { #if (CONFIG_BT_AUDIO_RX) { - .codec_cap = &lc3_codec, + .codec_cap = &lc3_codec_sink, }, #endif #if (CONFIG_BT_AUDIO_TX) { - .codec_cap = &lc3_codec, + .codec_cap = &lc3_codec_source, } #endif /* (CONFIG_BT_AUDIO_TX) */ }; @@ -177,48 +165,13 @@ static struct bt_bap_stream #if (CONFIG_BT_AUDIO_TX) BUILD_ASSERT(CONFIG_BT_ASCS_ASE_SRC_COUNT <= 1, "CIS headset only supports one source stream for now"); -static struct bt_audio_source { - struct bt_bap_stream *stream; - uint32_t seq_num; -} sources[CONFIG_BT_ASCS_ASE_SRC_COUNT]; #endif /* (CONFIG_BT_AUDIO_TX) */ -static void print_codec(const struct bt_audio_codec_cfg *codec, enum bt_audio_dir dir) -{ - if (codec->id == BT_HCI_CODING_FORMAT_LC3) { - /* LC3 uses the generic LTV format - other codecs might do as well */ - enum bt_audio_location chan_allocation; - - if (dir == BT_AUDIO_DIR_SINK) { - LOG_INF("LC3 codec config for sink:"); - } else if (dir == BT_AUDIO_DIR_SOURCE) { - LOG_INF("LC3 codec config for source:"); - } else { - LOG_INF("LC3 codec config for :"); - } - - LOG_INF("\tFrequency: %d Hz", bt_audio_codec_cfg_get_freq(codec)); - LOG_INF("\tFrame Duration: %d us", bt_audio_codec_cfg_get_frame_dur(codec)); - if (bt_audio_codec_cfg_get_chan_allocation(codec, &chan_allocation) == 0) { - LOG_INF("\tChannel allocation: 0x%x", chan_allocation); - } - - uint32_t octets_per_sdu = bt_audio_codec_cfg_get_octets_per_frame(codec); - uint32_t bitrate = octets_per_sdu * 8 * - (1000000 / bt_audio_codec_cfg_get_frame_dur(codec)); - - LOG_INF("\tOctets per frame: %d (%d bps)", octets_per_sdu, bitrate); - LOG_INF("\tFrames per SDU: %d", - bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec, true)); - } else { - LOG_WRN("Codec is not LC3, codec_id: 0x%2x", codec->id); - } -} - static int lc3_config_cb(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, const struct bt_audio_codec_cfg *codec, struct bt_bap_stream **stream, struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { + int ret; LOG_DBG("LC3 config callback"); for (int i = 0; i < ARRAY_SIZE(audio_streams); i++) { @@ -227,30 +180,31 @@ static int lc3_config_cb(struct bt_conn *conn, const struct bt_bap_ep *ep, enum if (!audio_stream->conn) { LOG_DBG("ASE Codec Config stream %p", (void *)audio_stream); - uint32_t octets_per_sdu = bt_audio_codec_cfg_get_octets_per_frame(codec); - - if (octets_per_sdu > LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX)) { - LOG_WRN("Too high bitrate"); + ret = le_audio_bitrate_check(codec); + if (!ret) { + LOG_WRN("Bitrate check failed"); return -EINVAL; - } else if (octets_per_sdu < - LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN)) { - LOG_WRN("Too low bitrate"); + } + + ret = le_audio_freq_check(codec); + if (!ret) { + LOG_WRN("Sample rate not supported"); return -EINVAL; } if (dir == BT_AUDIO_DIR_SINK) { LOG_DBG("BT_AUDIO_DIR_SINK"); - print_codec(codec, dir); - le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED, conn); + le_audio_print_codec(codec, dir); + le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED, conn, dir); } #if (CONFIG_BT_AUDIO_TX) else if (dir == BT_AUDIO_DIR_SOURCE) { LOG_DBG("BT_AUDIO_DIR_SOURCE"); - print_codec(codec, dir); - le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED, conn); + le_audio_print_codec(codec, dir); + le_audio_event_publish(LE_AUDIO_EVT_CONFIG_RECEIVED, conn, dir); /* CIS headset only supports one source stream for now */ - sources[0].stream = audio_stream; + bap_tx_streams[0] = audio_stream; } #endif /* (CONFIG_BT_AUDIO_TX) */ else { @@ -281,7 +235,15 @@ static int lc3_reconfig_cb(struct bt_bap_stream *stream, enum bt_audio_dir dir, static int lc3_qos_cb(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) { - le_audio_event_publish(LE_AUDIO_EVT_PRES_DELAY_SET, stream->conn); + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return -EIO; + } + + le_audio_event_publish(LE_AUDIO_EVT_PRES_DELAY_SET, stream->conn, dir); LOG_DBG("QoS: stream %p qos %p", (void *)stream, (void *)qos); @@ -311,27 +273,51 @@ static int lc3_metadata_cb(struct bt_bap_stream *stream, const uint8_t *meta, si static int lc3_disable_cb(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) { + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return -EIO; + } + LOG_DBG("Disable: stream %p", (void *)stream); - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, dir); return 0; } static int lc3_stop_cb(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) { + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return -EIO; + } + LOG_DBG("Stop: stream %p", (void *)stream); - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, dir); return 0; } static int lc3_release_cb(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) { + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return -EIO; + } + LOG_DBG("Release: stream %p", (void *)stream); - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, dir); return 0; } @@ -371,16 +357,25 @@ static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_rec #if (CONFIG_BT_AUDIO_TX) static void stream_sent_cb(struct bt_bap_stream *stream) { - atomic_dec(&iso_tx_pool_alloc); + /* Unicast server/CIS headset only supports one source stream for now */ + ERR_CHK(bt_le_audio_tx_stream_sent(0)); } #endif /* (CONFIG_BT_AUDIO_TX) */ static void stream_enabled_cb(struct bt_bap_stream *stream) { int ret; + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return; + } + LOG_DBG("Stream %p enabled", stream); - if (stream->ep->dir == BT_AUDIO_DIR_SINK) { + if (dir == BT_AUDIO_DIR_SINK) { /* Automatically do the receiver start ready operation */ ret = bt_bap_stream_start(stream); if (ret != 0) { @@ -397,20 +392,40 @@ static void stream_disabled_cb(struct bt_bap_stream *stream) static void stream_started_cb(struct bt_bap_stream *stream) { + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return; + } + LOG_INF("Stream %p started", stream); - le_audio_event_publish(LE_AUDIO_EVT_STREAMING, stream->conn); + if (dir == BT_AUDIO_DIR_SOURCE && IS_ENABLED(CONFIG_BT_AUDIO_TX)) { + ERR_CHK(bt_le_audio_tx_stream_started(0)); + } + + le_audio_event_publish(LE_AUDIO_EVT_STREAMING, stream->conn, dir); } static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) { + enum bt_audio_dir dir; + + dir = le_audio_stream_dir_get(stream); + if (dir <= 0) { + LOG_ERR("Failed to get dir of stream %p", stream); + return; + } + LOG_DBG("Stream %p stopped. Reason: %d", stream, reason); -#if (CONFIG_BT_AUDIO_TX) - atomic_clear(&iso_tx_pool_alloc); -#endif /* (CONFIG_BT_AUDIO_TX) */ + if (dir == BT_AUDIO_DIR_SOURCE && IS_ENABLED(CONFIG_BT_AUDIO_TX)) { + ERR_CHK(bt_le_audio_tx_stream_stopped(0)); + } - le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn); + le_audio_event_publish(LE_AUDIO_EVT_NOT_STREAMING, stream->conn, dir); } static void stream_released_cb(struct bt_bap_stream *stream) @@ -448,40 +463,84 @@ static int adv_buf_put(struct bt_data *adv_buf, uint8_t adv_buf_vacant, int *ind return 0; } -int unicast_server_config_get(uint32_t *bitrate, uint32_t *sampling_rate_hz, - uint32_t *pres_delay_us) +int unicast_server_config_get(struct bt_conn *conn, enum bt_audio_dir dir, uint32_t *bitrate, + uint32_t *sampling_rate_hz, uint32_t *pres_delay_us) { + int ret; + if (bitrate == NULL && sampling_rate_hz == NULL && pres_delay_us == NULL) { LOG_ERR("No valid pointers received"); return -ENXIO; } - if (audio_streams[0].codec_cfg == NULL) { - LOG_ERR("No codec found for the stream"); - return -ENXIO; - } + if (dir == BT_AUDIO_DIR_SINK) { + /* If multiple sink streams exists, they should have the same configurations, + * hence we only check the first one. + */ + if (audio_streams[0].codec_cfg == NULL) { + LOG_ERR("No codec found for the stream"); - if (sampling_rate_hz != NULL) { - *sampling_rate_hz = bt_audio_codec_cfg_get_freq(audio_streams[0].codec_cfg); - } + return -ENXIO; + } + + if (sampling_rate_hz != NULL) { + ret = le_audio_freq_hz_get(audio_streams[0].codec_cfg, sampling_rate_hz); + if (ret) { + LOG_ERR("Invalid sampling frequency: %d", ret); + return -ENXIO; + } + } - if (bitrate != NULL) { - /* Get the configuration for the sink stream */ - int frames_per_sec = 1000000 / bt_audio_codec_cfg_get_frame_dur( - audio_streams[0].codec_cfg); - int bits_per_frame = - bt_audio_codec_cfg_get_octets_per_frame(audio_streams[0].codec_cfg) * 8; + if (bitrate != NULL) { + ret = le_audio_bitrate_get(audio_streams[0].codec_cfg, bitrate); + if (ret) { + LOG_ERR("Unable to calculate bitrate: %d", ret); + return -ENXIO; + } + } - *bitrate = frames_per_sec * bits_per_frame; - } + if (pres_delay_us != NULL) { + if (audio_streams[0].qos == NULL) { + LOG_ERR("No QoS found for the stream"); + return -ENXIO; + } - if (pres_delay_us != NULL) { - if (audio_streams[0].qos == NULL) { - LOG_ERR("No QoS found for the stream"); + *pres_delay_us = audio_streams[0].qos->pd; + } + } else if (dir == BT_AUDIO_DIR_SOURCE && IS_ENABLED(CONFIG_BT_AUDIO_TX)) { + /* If multiple source streams exists, they should have the same configurations, + * hence we only check the first one. + */ + if (bap_tx_streams[0]->codec_cfg == NULL) { + LOG_ERR("No codec found for the stream"); return -ENXIO; } - *pres_delay_us = audio_streams[0].qos->pd; + if (sampling_rate_hz != NULL) { + ret = le_audio_freq_hz_get(bap_tx_streams[0]->codec_cfg, sampling_rate_hz); + if (ret) { + LOG_ERR("Invalid sampling frequency: %d", ret); + return -ENXIO; + } + } + + if (bitrate != NULL) { + ret = le_audio_bitrate_get(bap_tx_streams[0]->codec_cfg, bitrate); + if (ret) { + LOG_ERR("Unable to calculate bitrate: %d", ret); + return -ENXIO; + } + } + + if (pres_delay_us != NULL) { + if (bap_tx_streams[0]->qos == NULL) { + LOG_ERR("No QoS found for the stream"); + return -ENXIO; + } + + *pres_delay_us = bap_tx_streams[0]->qos->pd; + LOG_ERR("pres_delay_us: %d", *pres_delay_us); + } } return 0; @@ -545,59 +604,9 @@ int unicast_server_send(struct le_audio_encoded_audio enc_audio) { #if (CONFIG_BT_AUDIO_TX) int ret; - struct net_buf *buf; - static bool hci_wrn_printed; - - if (enc_audio.num_ch > CONFIG_BT_ASCS_ASE_SRC_COUNT) { - LOG_ERR("Trying to send %d channel(s), but %d ASEs are configured for source", - enc_audio.num_ch, CONFIG_BT_ASCS_ASE_SRC_COUNT); - return -EINVAL; - } - - /* CIS headset only supports one source stream for now */ - if (sources[0].stream->ep->status.state != BT_BAP_EP_STATE_STREAMING) { - LOG_DBG("Return channel not connected"); - return 0; - } - - /* net_buf_alloc allocates buffers for APP->NET transfer over HCI RPMsg, - * but when these buffers are released it is not guaranteed that the - * data has actually been sent. The data might be queued on the NET core, - * and this can cause delays in the audio. - * When stream_sent_cb() is called the data has been sent. - * Data will be discarded if allocation becomes too high, to avoid audio delays. - * If the NET and APP core operates in clock sync, discarding should not occur. - */ - if (atomic_get(&iso_tx_pool_alloc) >= HCI_ISO_BUF_ALLOC_PER_CHAN) { - if (!hci_wrn_printed) { - LOG_WRN("HCI ISO TX overrun"); - hci_wrn_printed = true; - } - - return -ENOMEM; - } - - hci_wrn_printed = false; - buf = net_buf_alloc(iso_tx_pools[0], K_NO_WAIT); - if (buf == NULL) { - /* This should never occur because of the iso_tx_pool_alloc - * check above - */ - LOG_WRN("Out of TX buffers"); - return -ENOMEM; - } - - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buf_add_mem(buf, enc_audio.data, enc_audio.size); - - atomic_inc(&iso_tx_pool_alloc); - ret = bt_bap_stream_send(sources[0].stream, buf, sources[0].seq_num++, - BT_ISO_TIMESTAMP_NONE); - if (ret < 0) { - LOG_WRN("Failed to send audio data: %d", ret); - net_buf_unref(buf); - atomic_dec(&iso_tx_pool_alloc); + ret = bt_le_audio_tx_send(bap_tx_streams, enc_audio, CONFIG_BT_ASCS_ASE_SRC_COUNT); + if (ret) { return ret; } @@ -633,6 +642,20 @@ int unicast_server_enable(le_audio_receive_cb recv_cb) channel_assignment_get(&channel); + if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA)) { + LOG_WRN("CSIP test sample data is used, must be changed " + "before production"); + } else { + if (strcmp(CONFIG_BT_SET_IDENTITY_RESOLVING_KEY_DEFAULT, + CONFIG_BT_SET_IDENTITY_RESOLVING_KEY) == 0) { + LOG_WRN("CSIP using the default SIRK, must be changed " + "before production"); + } + + memcpy(csip_param.set_sirk, CONFIG_BT_SET_IDENTITY_RESOLVING_KEY, + BT_CSIP_SET_SIRK_SIZE); + } + for (int i = 0; i < ARRAY_SIZE(caps); i++) { ret = bt_pacs_cap_register(caps_dirs[i], &caps[i]); if (ret) { @@ -665,39 +688,31 @@ int unicast_server_enable(le_audio_receive_cb recv_cb) } if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL)) { - ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_le_audio_tx_init(); + if (ret) { + return ret; + } + ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, AVAILABLE_SINK_CONTEXT); if (ret) { LOG_ERR("Supported context set failed. Err: %d", ret); return ret; } - ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, AVAILABLE_SINK_CONTEXT); if (ret) { LOG_ERR("Available context set failed. Err: %d", ret); return ret; } - ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, AVAILABLE_SOURCE_CONTEXT); if (ret) { LOG_ERR("Supported context set failed. Err: %d", ret); return ret; } - ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE, AVAILABLE_SOURCE_CONTEXT); if (ret) { LOG_ERR("Available context set failed. Err: %d", ret); return ret; @@ -722,18 +737,14 @@ int unicast_server_enable(le_audio_receive_cb recv_cb) return -ECANCELED; } } else { - ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, AVAILABLE_SINK_CONTEXT); if (ret) { LOG_ERR("Supported context set failed. Err: %d ", ret); return ret; } - ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, - BT_AUDIO_CONTEXT_TYPE_MEDIA | - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + ret = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, AVAILABLE_SINK_CONTEXT); if (ret) { LOG_ERR("Available context set failed. Err: %d", ret); diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.h index 033cc82455f..bb6a98374b0 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_server.h @@ -7,6 +7,7 @@ #ifndef _UNICAST_SERVER_H_ #define _UNICAST_SERVER_H_ +#include "bt_le_audio_tx.h" #include "le_audio.h" #include @@ -14,15 +15,18 @@ /** * @brief Get configuration for audio stream. * - * @param[out] bitrate Pointer to the bitrate used; can be NULL. + * @param[in] conn Pointer to the connection to get the configuration for. + * @param[in] dir Direction to get the configuration from. + * @param[out] bitrate Pointer to the bit rate used; can be NULL. * @param[out] sampling_rate_hz Pointer to the sampling rate used; can be NULL. - * @param[out] pres_delay_us Pointer to the presentation delay used; can be NULL. + * @param[out] pres_delay_us Pointer to the presentation delay used; can be NULL. Only + * valid for the sink direction. * * @retval 0 Operation successful. * @retval -ENXIO The feature is disabled. */ -int unicast_server_config_get(uint32_t *bitrate, uint32_t *sampling_rate_hz, - uint32_t *pres_delay_us); +int unicast_server_config_get(struct bt_conn *conn, enum bt_audio_dir dir, uint32_t *bitrate, + uint32_t *sampling_rate_hz, uint32_t *pres_delay_us); /** * @brief Put the UUIDs from this module into the buffer. @@ -43,7 +47,7 @@ int unicast_server_uuid_populate(struct net_buf_simple *uuid_buf); * @param[out] adv_buf Buffer being populated with ext adv elements. * @param[in] adv_buf_vacant Number of vacant elements in @p adv_buf. * - * @return Negative values for errors or num elements added to @p adv_buf. + * @return Negative values for errors or number of elements added to @p adv_buf. */ int unicast_server_adv_populate(struct bt_data *adv_buf, uint8_t adv_buf_vacant); diff --git a/applications/nrf5340_audio/src/bluetooth/le_audio.h b/applications/nrf5340_audio/src/bluetooth/le_audio.h deleted file mode 100644 index 4e0ddc10ddd..00000000000 --- a/applications/nrf5340_audio/src/bluetooth/le_audio.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef _LE_AUDIO_H_ -#define _LE_AUDIO_H_ - -#include -#include - -#define LE_AUDIO_ZBUS_EVENT_WAIT_TIME K_MSEC(5) -#define LE_AUDIO_SDU_SIZE_OCTETS(bitrate) (bitrate / (1000000 / CONFIG_AUDIO_FRAME_DURATION_US) / 8) - -#if (CONFIG_AUDIO_SAMPLE_RATE_48000_HZ) -#define BT_AUDIO_CODEC_CONFIG_FREQ BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ -#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_LC3_FREQ_48KHZ -#elif (CONFIG_AUDIO_SAMPLE_RATE_24000_HZ) -#define BT_AUDIO_CODEC_CONFIG_FREQ BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ -#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_LC3_FREQ_24KHZ -#elif (CONFIG_AUDIO_SAMPLE_RATE_16000_HZ) -#define BT_AUDIO_CODEC_CONFIG_FREQ BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ -#define BT_AUDIO_CODEC_CAPABILIY_FREQ BT_AUDIO_CODEC_LC3_FREQ_16KHZ -#endif /* (CONFIG_AUDIO_SAMPLE_RATE_48000_HZ) */ - -#define BT_BAP_LC3_PRESET_CONFIGURABLE(_loc, _stream_context, _bitrate) \ - BT_BAP_LC3_PRESET( \ - BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_FREQ, \ - BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, \ - LE_AUDIO_SDU_SIZE_OCTETS(_bitrate), 1, _stream_context), \ - BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(LE_AUDIO_SDU_SIZE_OCTETS(_bitrate), \ - CONFIG_BT_AUDIO_RETRANSMITS, \ - CONFIG_BT_AUDIO_MAX_TRANSPORT_LATENCY_MS, \ - CONFIG_BT_AUDIO_PRESENTATION_DELAY_US)) - -/** - * @brief Callback for receiving Bluetooth LE Audio data. - * - * @param data Pointer to received data. - * @param size Size of received data. - * @param bad_frame Indicating if the frame is a bad frame or not. - * @param sdu_ref ISO timestamp. - * @param channel_index Audio channel index. - */ -typedef void (*le_audio_receive_cb)(const uint8_t *const data, size_t size, bool bad_frame, - uint32_t sdu_ref, enum audio_channel channel_index, - size_t desired_size); - -/** - * @brief Encoded audio data and information. - * - * @note Container for SW codec (typically LC3) compressed audio data. - */ -struct le_audio_encoded_audio { - uint8_t const *const data; - size_t size; - uint8_t num_ch; -}; - -#endif /* _LE_AUDIO_H_ */ diff --git a/applications/nrf5340_audio/src/main.c b/applications/nrf5340_audio/src/main.c deleted file mode 100644 index 88e0630b48d..00000000000 --- a/applications/nrf5340_audio/src/main.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2018 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include -#include -#include - -#include "macros_common.h" -#include "nrf5340_audio_common.h" -#include "fw_info_app.h" -#include "led.h" -#include "button_handler.h" -#include "button_assignments.h" -#include "nrfx_clock.h" -#include "sd_card.h" -#include "bt_mgmt.h" -#include "board_version.h" -#include "channel_assignment.h" -#include "streamctrl.h" -#include "sd_card_playback.h" - -#include -LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL); - -static struct board_version board_rev; - -static int hfclock_config_and_start(void) -{ - int ret; - - /* Use this to turn on 128 MHz clock for cpu_app */ - ret = nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1); - - ret -= NRFX_ERROR_BASE_NUM; - if (ret) { - return ret; - } - - nrfx_clock_hfclk_start(); - while (!nrfx_clock_hfclk_is_running()) { - } - - return 0; -} - -static int leds_set(void) -{ - int ret; - - /* Blink LED 3 to indicate that APP core is running */ - ret = led_blink(LED_APP_3_GREEN); - if (ret) { - return ret; - } - -#if (CONFIG_AUDIO_DEV == HEADSET) - enum audio_channel channel; - - channel_assignment_get(&channel); - - if (channel == AUDIO_CH_L) { - ret = led_on(LED_APP_RGB, LED_COLOR_BLUE); - } else { - ret = led_on(LED_APP_RGB, LED_COLOR_MAGENTA); - } - - if (ret) { - return ret; - } -#elif (CONFIG_AUDIO_DEV == GATEWAY) - ret = led_on(LED_APP_RGB, LED_COLOR_GREEN); - if (ret) { - return ret; - } -#endif /* (CONFIG_AUDIO_DEV == HEADSET) */ - - return 0; -} - -static int channel_assign_check(void) -{ -#if (CONFIG_AUDIO_DEV == HEADSET) && CONFIG_AUDIO_HEADSET_CHANNEL_RUNTIME - int ret; - bool pressed; - - ret = button_pressed(BUTTON_VOLUME_DOWN, &pressed); - if (ret) { - return ret; - } - - if (pressed) { - channel_assignment_set(AUDIO_CH_L); - return 0; - } - - ret = button_pressed(BUTTON_VOLUME_UP, &pressed); - if (ret) { - return ret; - } - - if (pressed) { - channel_assignment_set(AUDIO_CH_R); - return 0; - } -#endif - - return 0; -} - -int main(void) -{ - int ret; - - LOG_DBG("nRF5340 APP core started"); - - ret = hfclock_config_and_start(); - ERR_CHK(ret); - - ret = led_init(); - ERR_CHK(ret); - - ret = button_handler_init(); - ERR_CHK(ret); - - channel_assignment_init(); - - ret = channel_assign_check(); - ERR_CHK(ret); - - ret = fw_info_app_print(); - ERR_CHK(ret); - - ret = board_version_valid_check(); - ERR_CHK(ret); - - ret = board_version_get(&board_rev); - ERR_CHK(ret); - - if (board_rev.mask & BOARD_VERSION_VALID_MSK_SD_CARD) { - ret = sd_card_init(); - if (ret != -ENODEV) { - ERR_CHK(ret); - } - } - - ret = bt_mgmt_init(); - ERR_CHK(ret); - - ret = leds_set(); - ERR_CHK(ret); - - ret = streamctrl_start(); - ERR_CHK(ret); - - if (IS_ENABLED(CONFIG_SD_CARD_PLAYBACK)) { - sd_card_playback_init(); - } -} diff --git a/applications/nrf5340_audio/src/modules/CMakeLists.txt b/applications/nrf5340_audio/src/modules/CMakeLists.txt index 535e453b350..a1734af98d2 100644 --- a/applications/nrf5340_audio/src/modules/CMakeLists.txt +++ b/applications/nrf5340_audio/src/modules/CMakeLists.txt @@ -14,11 +14,7 @@ set(SRCS ${CMAKE_CURRENT_SOURCE_DIR}/sd_card.c ) -if (CONFIG_AUDIO_SYNC_TIMER_USES_RTC) - list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/audio_sync_timer_rtc.c) -else() - list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/audio_sync_timer.c) -endif() +list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/audio_sync_timer_rtc.c) if (CONFIG_SD_CARD_PLAYBACK) list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/sd_card_playback.c) diff --git a/applications/nrf5340_audio/src/modules/Kconfig b/applications/nrf5340_audio/src/modules/Kconfig index 4d704feacc1..424b46387f7 100644 --- a/applications/nrf5340_audio/src/modules/Kconfig +++ b/applications/nrf5340_audio/src/modules/Kconfig @@ -14,7 +14,7 @@ config BUTTON_DEBOUNCE_MS config AUDIO_SYNC_TIMER_USES_RTC bool - default !BT_LL_ACS_NRF53 + default y select NRFX_RTC0 #----------------------------------------------------------------------------# @@ -89,6 +89,10 @@ module = MODULE_SD_CARD_PLAYBACK module-str = module-sd-card-playback source "subsys/logging/Kconfig.template.log_config" +module = MODULE_NRF5340_AUDIO_DK +module-str = module-nrf5340-audio_dk +source "subsys/logging/Kconfig.template.log_config" + endmenu # Log levels #----------------------------------------------------------------------------# diff --git a/applications/nrf5340_audio/src/modules/audio_i2s.c b/applications/nrf5340_audio/src/modules/audio_i2s.c index 02706fba071..d8c113ae644 100644 --- a/applications/nrf5340_audio/src/modules/audio_i2s.c +++ b/applications/nrf5340_audio/src/modules/audio_i2s.c @@ -86,8 +86,9 @@ void audio_i2s_set_next_buf(const uint8_t *tx_buf, uint32_t *rx_buf) __ASSERT_NO_MSG(tx_buf != NULL); } - const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf, - .p_tx_buffer = (uint32_t *)tx_buf }; + const nrfx_i2s_buffers_t i2s_buf = {.p_rx_buffer = rx_buf, + .p_tx_buffer = (uint32_t *)tx_buf, + .buffer_size = I2S_SAMPLES_NUM}; nrfx_err_t ret; @@ -106,13 +107,14 @@ void audio_i2s_start(const uint8_t *tx_buf, uint32_t *rx_buf) __ASSERT_NO_MSG(tx_buf != NULL); } - const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf, - .p_tx_buffer = (uint32_t *)tx_buf }; + const nrfx_i2s_buffers_t i2s_buf = {.p_rx_buffer = rx_buf, + .p_tx_buffer = (uint32_t *)tx_buf, + .buffer_size = I2S_SAMPLES_NUM}; nrfx_err_t ret; /* Buffer size in 32-bit words */ - ret = nrfx_i2s_start(&i2s_inst, &i2s_buf, I2S_SAMPLES_NUM, 0); + ret = nrfx_i2s_start(&i2s_inst, &i2s_buf, 0); __ASSERT_NO_MSG(ret == NRFX_SUCCESS); state = AUDIO_I2S_STATE_STARTED; diff --git a/applications/nrf5340_audio/src/modules/audio_sync_timer.c b/applications/nrf5340_audio/src/modules/audio_sync_timer.c deleted file mode 100644 index 483ebbe8e85..00000000000 --- a/applications/nrf5340_audio/src/modules/audio_sync_timer.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2021, PACKETCRAFT, INC. - * - * SPDX-License-Identifier: LicenseRef-PCFT - */ - -#include "audio_sync_timer.h" - -#include -#include -#include -#include -#include -#include - - -#include -LOG_MODULE_REGISTER(audio_sync_timer, CONFIG_AUDIO_SYNC_TIMER_LOG_LEVEL); - -#define AUDIO_SYNC_TIMER_INSTANCE_NUMBER 1 - -#define AUDIO_SYNC_TIMER_I2S_FRAME_START_EVT_CAPTURE_CHANNEL 0 -#define AUDIO_SYNC_TIMER_CURR_TIME_CAPTURE_CHANNEL 1 -#define AUDIO_SYNC_TIMER_I2S_FRAME_START_EVT_CAPTURE NRF_TIMER_TASK_CAPTURE0 - -#define AUDIO_SYNC_TIMER_NET_APP_IPC_EVT NRF_IPC_EVENT_RECEIVE_4 - -static const nrfx_timer_t audio_sync_timer_instance = - NRFX_TIMER_INSTANCE(AUDIO_SYNC_TIMER_INSTANCE_NUMBER); - -static uint8_t dppi_channel_timer_clear; -static uint8_t dppi_channel_i2s_frame_start; - -static nrfx_timer_config_t cfg = {.frequency = NRFX_MHZ_TO_HZ(1UL), - .mode = NRF_TIMER_MODE_TIMER, - .bit_width = NRF_TIMER_BIT_WIDTH_32, - .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, - .p_context = NULL}; - -uint32_t audio_sync_timer_capture(void) -{ - return nrfx_timer_capture(&audio_sync_timer_instance, - AUDIO_SYNC_TIMER_CURR_TIME_CAPTURE_CHANNEL); -} - -uint32_t audio_sync_timer_capture_get(void) -{ - return nrfx_timer_capture_get(&audio_sync_timer_instance, - AUDIO_SYNC_TIMER_I2S_FRAME_START_EVT_CAPTURE_CHANNEL); -} - -static void event_handler(nrf_timer_event_t event_type, void *ctx) -{ -} - -/** - * @brief Initialize audio sync timer - * - * @note Clearing of the nRF5340 APP core sync - * timer is initialized here. The sync timers on - * APP core and NET core are cleared at exactly - * the same time using an IPC signal sent from - * the NET core. This makes the two timers - * synchronized. - * - * @param unused Unused - * - * @return 0 if successful, error otherwise - */ -static int audio_sync_timer_init(void) -{ - nrfx_err_t ret; - - ret = nrfx_timer_init(&audio_sync_timer_instance, &cfg, event_handler); - if (ret - NRFX_ERROR_BASE_NUM) { - LOG_ERR("nrfx timer init error - Return value: %d", ret); - return ret; - } - - nrfx_timer_enable(&audio_sync_timer_instance); - - /* Initialize capturing of I2S frame start event timestamps */ - ret = nrfx_dppi_channel_alloc(&dppi_channel_i2s_frame_start); - if (ret - NRFX_ERROR_BASE_NUM) { - LOG_ERR("nrfx DPPI channel alloc error (I2S frame start) - Return value: %d", ret); - return ret; - } - - nrf_timer_subscribe_set(audio_sync_timer_instance.p_reg, - AUDIO_SYNC_TIMER_I2S_FRAME_START_EVT_CAPTURE, - dppi_channel_i2s_frame_start); - nrf_i2s_publish_set(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART, dppi_channel_i2s_frame_start); - ret = nrfx_dppi_channel_enable(dppi_channel_i2s_frame_start); - if (ret - NRFX_ERROR_BASE_NUM) { - LOG_ERR("nrfx DPPI channel enable error (I2S frame start) - Return value: %d", ret); - return ret; - } - - /* Initialize functionality for synchronization between APP and NET core */ - ret = nrfx_dppi_channel_alloc(&dppi_channel_timer_clear); - if (ret - NRFX_ERROR_BASE_NUM) { - LOG_ERR("nrfx DPPI channel alloc error (timer clear) - Return value: %d", ret); - return ret; - } - - nrf_ipc_publish_set(NRF_IPC, AUDIO_SYNC_TIMER_NET_APP_IPC_EVT, dppi_channel_timer_clear); - nrf_timer_subscribe_set(audio_sync_timer_instance.p_reg, NRF_TIMER_TASK_CLEAR, - dppi_channel_timer_clear); - ret = nrfx_dppi_channel_enable(dppi_channel_timer_clear); - if (ret - NRFX_ERROR_BASE_NUM) { - LOG_ERR("nrfx DPPI channel enable error (timer clear) - Return value: %d", ret); - return ret; - } - - LOG_DBG("Audio sync timer initialized"); - - return 0; -} - -SYS_INIT(audio_sync_timer_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/applications/nrf5340_audio/src/modules/audio_usb.c b/applications/nrf5340_audio/src/modules/audio_usb.c index d651232b203..3e9c749e668 100644 --- a/applications/nrf5340_audio/src/modules/audio_usb.c +++ b/applications/nrf5340_audio/src/modules/audio_usb.c @@ -25,7 +25,13 @@ static struct data_fifo *fifo_rx; NET_BUF_POOL_FIXED_DEFINE(pool_out, CONFIG_FIFO_FRAME_SPLIT_NUM, USB_FRAME_SIZE_STEREO, 8, net_buf_destroy); +static uint32_t rx_num_overruns; +static bool rx_first_data; +static bool tx_first_data; + #if (CONFIG_STREAM_BIDIRECTIONAL) +static uint32_t tx_num_underruns; + static void data_write(const struct device *dev) { int ret; @@ -42,9 +48,12 @@ static void data_write(const struct device *dev) ret = data_fifo_pointer_last_filled_get(fifo_tx, &data_out, &data_out_size, K_NO_WAIT); if (ret) { - /* NOTE: The string below is used by the Nordic CI system */ - LOG_WRN("USB TX underrun"); + tx_num_underruns++; + if ((tx_num_underruns % 100) == 1) { + LOG_WRN("USB TX underrun. Num: %d", tx_num_underruns); + } net_buf_unref(buf_out); + return; } @@ -61,6 +70,11 @@ static void data_write(const struct device *dev) } else { LOG_WRN("Wrong size write: %d", data_out_size); } + + if (!tx_first_data) { + LOG_INF("USB TX first data sent."); + tx_first_data = true; + } } #endif /* (CONFIG_STREAM_BIDIRECTIONAL) */ @@ -94,7 +108,10 @@ static void data_received(const struct device *dev, struct net_buf *buffer, size void *temp; size_t temp_size; - LOG_WRN("USB RX overrun"); + rx_num_overruns++; + if ((rx_num_overruns % 100) == 1) { + LOG_WRN("USB RX overrun. Num: %d", rx_num_overruns); + } ret = data_fifo_pointer_last_filled_get(fifo_rx, &temp, &temp_size, K_NO_WAIT); ERR_CHK(ret); @@ -112,6 +129,11 @@ static void data_received(const struct device *dev, struct net_buf *buffer, size ERR_CHK_MSG(ret, "Failed to lock block"); net_buf_unref(buffer); + + if (!rx_first_data) { + LOG_INF("USB RX first data received."); + rx_first_data = true; + } } static void feature_update(const struct device *dev, const struct usb_audio_fu_evt *evt) @@ -147,6 +169,8 @@ int audio_usb_start(struct data_fifo *fifo_tx_in, struct data_fifo *fifo_rx_in) void audio_usb_stop(void) { + rx_first_data = false; + tx_first_data = false; fifo_tx = NULL; fifo_rx = NULL; } @@ -184,5 +208,7 @@ int audio_usb_init(void) return ret; } + LOG_INF("Ready for USB host to send/receive."); + return 0; } diff --git a/applications/nrf5340_audio/src/modules/power_meas.c b/applications/nrf5340_audio/src/modules/power_meas.c index d5dfb738af6..836dbfea3a3 100644 --- a/applications/nrf5340_audio/src/modules/power_meas.c +++ b/applications/nrf5340_audio/src/modules/power_meas.c @@ -68,8 +68,8 @@ static int read_and_log(const struct power_rail_config *config) } LOG_INF("%-10s:\t%.3fV, %06.3fmA, %06.3fmW", config->name, sensor_value_to_double(&voltage), - sensor_value_to_double(¤t) * 1000.0f, - sensor_value_to_double(&power) * 1000.0f); + sensor_value_to_double(¤t) * 1000.0, + sensor_value_to_double(&power) * 1000.0); return 0; } diff --git a/applications/nrf5340_audio/src/modules/sd_card_playback.c b/applications/nrf5340_audio/src/modules/sd_card_playback.c index 82410907ced..f115105ebec 100644 --- a/applications/nrf5340_audio/src/modules/sd_card_playback.c +++ b/applications/nrf5340_audio/src/modules/sd_card_playback.c @@ -493,6 +493,10 @@ static int cmd_play_wav_file(const struct shell *shell, size_t argc, char **argv return -EINVAL; } + if ((strlen(playback_file_path) + strlen(argv[1])) >= ARRAY_SIZE(file_loc)) { + return -ENOMEM; + } + strcat(file_loc, playback_file_path); strcat(file_loc, argv[1]); ret = sd_card_playback_wav(file_loc); @@ -515,6 +519,10 @@ static int cmd_play_lc3_file(const struct shell *shell, size_t argc, char **argv char file_loc[MAX_PATH_LEN] = ""; + if ((strlen(playback_file_path) + strlen(argv[1])) >= ARRAY_SIZE(file_loc)) { + return -ENOMEM; + } + strcat(file_loc, playback_file_path); strcat(file_loc, argv[1]); ret = sd_card_playback_lc3(file_loc); @@ -537,6 +545,11 @@ static int cmd_change_dir(const struct shell *shell, size_t argc, char **argv) playback_file_path[0] = '\0'; shell_print(shell, "Current directory: root"); } else { + if ((strlen(playback_file_path) + strlen(argv[1])) >= + ARRAY_SIZE(playback_file_path)) { + return -ENOMEM; + } + strcat(playback_file_path, argv[1]); strcat(playback_file_path, "/"); shell_print(shell, "Current directory: %s", playback_file_path); diff --git a/applications/nrf5340_audio/src/nrf5340_audio_common.c b/applications/nrf5340_audio/src/nrf5340_audio_common.c new file mode 100644 index 00000000000..bf16246c48e --- /dev/null +++ b/applications/nrf5340_audio/src/nrf5340_audio_common.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bt_mgmt.h" +#include "fw_info_app.h" + +#include +LOG_MODULE_REGISTER(nrf5340_audio_common, CONFIG_NRF5340_AUDIO_COMMON_LOG_LEVEL); + +int nrf5340_audio_common_init(void) +{ + int ret; + + ret = fw_info_app_print(); + if (ret) { + LOG_ERR("Failed to print application FW info"); + return ret; + } + + ret = bt_mgmt_init(); + if (ret) { + LOG_ERR("Failed to initialize bt_mgmt"); + return ret; + } + + return 0; +} diff --git a/applications/nrf5340_audio/src/utils/CMakeLists.txt b/applications/nrf5340_audio/src/utils/CMakeLists.txt index 4b4e539418d..d31257a3c23 100644 --- a/applications/nrf5340_audio/src/utils/CMakeLists.txt +++ b/applications/nrf5340_audio/src/utils/CMakeLists.txt @@ -9,4 +9,5 @@ target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/channel_assignment.c ${CMAKE_CURRENT_SOURCE_DIR}/error_handler.c ${CMAKE_CURRENT_SOURCE_DIR}/uicr.c + ${CMAKE_CURRENT_SOURCE_DIR}/nrf5340_audio_dk.c ) diff --git a/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.c b/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.c new file mode 100644 index 00000000000..f6813be3c28 --- /dev/null +++ b/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "led.h" +#include "button_handler.h" +#include "button_assignments.h" +#include "nrfx_clock.h" +#include "sd_card.h" +#include "board_version.h" +#include "channel_assignment.h" +#include "audio_system.h" + +#include "sd_card_playback.h" + +#include +LOG_MODULE_REGISTER(nrf5340_audio_dk, CONFIG_MODULE_NRF5340_AUDIO_DK_LOG_LEVEL); + +static struct board_version board_rev; + +static int hfclock_config_and_start(void) +{ + int ret; + + /* Use this to turn on 128 MHz clock for cpu_app */ + ret = nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1); + + ret -= NRFX_ERROR_BASE_NUM; + if (ret) { + return ret; + } + + return 0; +} + +static int leds_set(void) +{ + int ret; + + /* Blink LED 3 to indicate that APP core is running */ + ret = led_blink(LED_APP_3_GREEN); + if (ret) { + return ret; + } + +#if (CONFIG_AUDIO_DEV == HEADSET) + enum audio_channel channel; + + channel_assignment_get(&channel); + + if (channel == AUDIO_CH_L) { + ret = led_on(LED_APP_RGB, LED_COLOR_BLUE); + } else { + ret = led_on(LED_APP_RGB, LED_COLOR_MAGENTA); + } + + if (ret) { + return ret; + } +#elif (CONFIG_AUDIO_DEV == GATEWAY) + ret = led_on(LED_APP_RGB, LED_COLOR_GREEN); + if (ret) { + return ret; + } +#endif /* (CONFIG_AUDIO_DEV == HEADSET) */ + + return 0; +} + +static int channel_assign_check(void) +{ +#if (CONFIG_AUDIO_DEV == HEADSET) && CONFIG_AUDIO_HEADSET_CHANNEL_RUNTIME + int ret; + bool pressed; + + ret = button_pressed(BUTTON_VOLUME_DOWN, &pressed); + if (ret) { + return ret; + } + + if (pressed) { + channel_assignment_set(AUDIO_CH_L); + return 0; + } + + ret = button_pressed(BUTTON_VOLUME_UP, &pressed); + if (ret) { + return ret; + } + + if (pressed) { + channel_assignment_set(AUDIO_CH_R); + return 0; + } +#endif + + return 0; +} + +int nrf5340_audio_dk_init(void) +{ + int ret; + + ret = hfclock_config_and_start(); + if (ret) { + return ret; + } + + ret = led_init(); + if (ret) { + LOG_ERR("Failed to initialize LED module"); + return ret; + } + + ret = button_handler_init(); + if (ret) { + LOG_ERR("Failed to initialize button handler"); + return ret; + } + + channel_assignment_init(); + + ret = channel_assign_check(); + if (ret) { + LOG_ERR("Failed get channel assignment"); + return ret; + } + + ret = board_version_valid_check(); + if (ret) { + return ret; + } + + ret = board_version_get(&board_rev); + if (ret) { + return ret; + } + + if (board_rev.mask & BOARD_VERSION_VALID_MSK_SD_CARD) { + ret = sd_card_init(); + if (ret != -ENODEV && ret != 0) { + LOG_ERR("Failed to initialize SD card"); + return ret; + } + } + + ret = leds_set(); + if (ret) { + LOG_ERR("Failed to set LEDs"); + return ret; + } + + if (IS_ENABLED(CONFIG_SD_CARD_PLAYBACK)) { + ret = sd_card_playback_init(); + if (ret) { + LOG_ERR("Failed to initialize SD card playback"); + return ret; + } + } + + ret = audio_system_init(); + if (ret) { + LOG_ERR("Failed to initialize the audio system"); + return ret; + } + + return 0; +} diff --git a/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.h b/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.h new file mode 100644 index 00000000000..1fdcc86b08c --- /dev/null +++ b/applications/nrf5340_audio/src/utils/nrf5340_audio_dk.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @brief Initialize the hardware related modules on the nRF5340 Audio DK/PCA10121 + * + * @return 0 if successful, error otherwise. + */ +int nrf5340_audio_dk_init(void); diff --git a/applications/nrf5340_audio/tools/buildprog/ble5-ctr-rpmsg_sign.py b/applications/nrf5340_audio/tools/buildprog/ble5-ctr-rpmsg_sign.py deleted file mode 100644 index b39216867fe..00000000000 --- a/applications/nrf5340_audio/tools/buildprog/ble5-ctr-rpmsg_sign.py +++ /dev/null @@ -1,309 +0,0 @@ -# -# Copyright (c) 2022 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - -""" -Sign ble5-ctr-rpmsg BT Controller with B0N -""" - -import argparse -import sys -import shutil -import os -from pathlib import Path -import re - -BLE5_CTR_HEX = 'new_fw_info_ble5-ctr.hex' -FINAL_BLE5_CTR_HEX = 'ble5-ctr_CPUNET.hex' -FINAL_BLE5_CTR_UPDATE_BIN = 'ble5-ctr_net_core_update.bin' -ORIG_BLE5_CTR_PATTERN = r'ble5-ctr-rpmsg_shifted_\d{4}.hex' -ORIG_BLE5_CTR_MIN_PATTERN = r'ble5-ctr-rpmsg_shifted_min_\d{4}.hex' -NET_CORE_APP_NAME = 'empty_net_core' - -ZEPHYR_BASE = os.environ['ZEPHYR_BASE'] -MANUALLY_SIGN_DIR = Path(__file__).resolve().parent -BIN_DIR = (MANUALLY_SIGN_DIR / '../../bin').resolve() - - -def awklike(field_str, filename): - """ A function like unix awk to split string""" - ret = '' - try: - with open(filename, encoding='utf8') as file_pointer: - for line in file_pointer: - if field_str in line: - ret = line.replace(field_str, '').replace( - '\n', '').replace('"', '') - break - except (OSError, IOError) as exp: - print(exp) - return ret - - -def sign(orig_hex, build_dir): - """ A function to combine and sign ble5-ctr-""" - - if os.name == 'nt': - folder_slash = '\\' - else: - folder_slash = '/' - - # RETEIVE setting value from .config - # "${ZEPHYR_BASE}/../bootloader/mcuboot/root-rsa-2048.pem" - - mcuboot_rsa_key = awklike('CONFIG_BOOT_SIGNATURE_KEY_FILE=', build_dir + - '/mcuboot/zephyr/.config') - - # '\\' is used for Windows, '/' is used for other Operating Systems like Linux. - if ('/' in mcuboot_rsa_key) or ('\\' in mcuboot_rsa_key): - print('absolute path') - # Zephyr script convert folder separator to '/'. Should do the same here no matter Windows or not. - if folder_slash in mcuboot_rsa_key: - mcuboot_rsa_key.replace(folder_slash, '/') - else: - print('relative path') - mcuboot_rsa_key = ZEPHYR_BASE + '/../bootloader/mcuboot/' + mcuboot_rsa_key - - # IMAGE_VERSION="0.0.0+1" - image_version = awklike('CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION=', - build_dir + '/zephyr/.config') - # VALIDATION_MAGIC_VALUE="0x281ee6de,0x86518483,79106" - fw_info_magic_common = awklike('CONFIG_FW_INFO_MAGIC_COMMON=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - fw_info_magic_firmware_info = awklike('CONFIG_FW_INFO_MAGIC_FIRMWARE_INFO=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - sb_validation_info_magic = awklike('CONFIG_SB_VALIDATION_INFO_MAGIC=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - fw_info_firmware_version = awklike('CONFIG_FW_INFO_FIRMWARE_VERSION=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - fw_info_valid_val = awklike('CONFIG_FW_INFO_VALID_VAL=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - temp_ver = int(awklike('CONFIG_SB_VALIDATION_INFO_VERSION=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config')) - temp_hwid = int(awklike('CONFIG_FW_INFO_HARDWARE_ID=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config')) - temp_valid_crypto_id = int(awklike('CONFIG_SB_VALIDATION_INFO_CRYPTO_ID=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config')) - temp_crypto_id = int(awklike('CONFIG_FW_INFO_CRYPTO_ID=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config')) - temp_compat_id = int(awklike('CONFIG_FW_INFO_MAGIC_COMPATIBILITY_ID=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config')) - magic_compatibility_validation_info = temp_ver + (temp_hwid << 8) + (temp_valid_crypto_id << 16)\ - + (temp_compat_id << 24) - magic_compatibility_info = temp_ver + (temp_hwid << 8) + (temp_crypto_id << 16)\ - + (temp_compat_id << 24) - - validation_magic_value = f'{fw_info_magic_common},{sb_validation_info_magic},\ -{magic_compatibility_validation_info}' - - firmware_info_magic = f'{fw_info_magic_common},{fw_info_magic_firmware_info},\ -{magic_compatibility_info}' - - # 0x01008800 - pm_net_app_address = int(awklike('PM_APP_ADDRESS=', build_dir + - f'/{NET_CORE_APP_NAME}/pm_CPUNET.config'), 16) - # 0xc200/0x10200 - #PM_APP_APP_ADDRESS = int(awklike('PM_APP_ADDRESS=', build_dir + '/pm.config'), 16) - pm_app_app_address = awklike('PM_APP_ADDRESS=', build_dir + '/pm.config') - # CONFIG_FW_INFO_OFFSET 0x200 - fw_info_offset = int(awklike('CONFIG_FW_INFO_OFFSET=', build_dir + - f'/{NET_CORE_APP_NAME}/b0n/zephyr/.config'), 16) - # nRF5340_CPUAPP_QKAA - soc_name = awklike('CONFIG_SOC=', build_dir + '/zephyr/.config') - # nRF5340_CPUNET_QKAA - net_soc_name = awklike('CONFIG_SOC=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config') - # CONFIG_DOMAIN_CPUNET_BOARD net_core_app_update.binboard - net_core_app_binboard = awklike( - 'CONFIG_DOMAIN_CPUNET_BOARD=', build_dir + '/zephyr/.config') - # CONFIG_BOARD="nrf5340_audio_nrf5340_cpuapp" - config_board = awklike('CONFIG_BOARD=', build_dir + '/zephyr/.config') - - net_core_fw_info_address = pm_net_app_address + fw_info_offset - net_core_fw_info_address = f'0x{net_core_fw_info_address:08X}' - - # Inject FW_INFO from .config - os_cmd = f'{sys.executable} {MANUALLY_SIGN_DIR}/fw_info_data.py --input {orig_hex} --output-hex {build_dir}/{BLE5_CTR_HEX}\ - --offset {net_core_fw_info_address} --magic-value {firmware_info_magic}\ - --fw-version {fw_info_firmware_version} --fw-valid-val {fw_info_valid_val}' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - # 240 - num_ver_counter_slots = int(awklike('CONFIG_SB_NUM_VER_COUNTER_SLOTS=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config'), 10) - pm_partition_size_provision = int(awklike('CONFIG_PM_PARTITION_SIZE_PROVISION=', build_dir + - f'/{NET_CORE_APP_NAME}/zephyr/.config'), 16) - cpunet_pm_app_address = hex(int(awklike('PM_APP_ADDRESS=', build_dir + - f'/{NET_CORE_APP_NAME}/pm_CPUNET.config'), 16)) - pm_provision_address = int(awklike('PM_PROVISION_ADDRESS=', build_dir + - f'/{NET_CORE_APP_NAME}/pm_CPUNET.config'), 16) - pm_mcuboot_secondary_size = int(awklike('PM_MCUBOOT_SECONDARY_SIZE=', build_dir + - '/pm.config'), 16) - - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../nrf/scripts/bootloader/hash.py --in {build_dir}/{BLE5_CTR_HEX}\ - > {build_dir}/app_firmware.sha256' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../nrf/scripts/bootloader/do_sign.py --private-key\ - {build_dir}/{NET_CORE_APP_NAME}/zephyr/GENERATED_NON_SECURE_SIGN_KEY_PRIVATE.pem --in\ - {build_dir}/app_firmware.sha256 > {build_dir}/app_firmware.signature' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - public_keys = f' {build_dir}/{NET_CORE_APP_NAME}/zephyr/nrf/subsys/bootloader/generated/public.pem' - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../nrf/scripts/bootloader/validation_data.py\ - --input {build_dir}/{BLE5_CTR_HEX} --output-hex {build_dir}/signed_by_b0_ble5_ctr.hex\ - --output-bin {build_dir}/signed_by_b0_ble5_ctr.bin --offset 0 --signature\ - {build_dir}/app_firmware.signature --public-key {public_keys}\ - --magic-value {validation_magic_value}' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - # Generate net_core_app_update.bin - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../bootloader/mcuboot/scripts/imgtool.py sign --key\ - {mcuboot_rsa_key} --header-size {fw_info_offset} --align 4 --version {image_version}\ - --pad-header --slot-size {pm_mcuboot_secondary_size} {build_dir}/signed_by_b0_ble5_ctr.bin\ - {build_dir}/{FINAL_BLE5_CTR_UPDATE_BIN}' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - # Check if debug key exists - debug_public_key_0 = Path(f'{build_dir}/{NET_CORE_APP_NAME}/zephyr/GENERATED_NON_SECURE_PUBLIC_0.pem').resolve() - debug_public_key_1 = Path(f'{build_dir}/{NET_CORE_APP_NAME}/zephyr/GENERATED_NON_SECURE_PUBLIC_1.pem').resolve() - if debug_public_key_0.exists(): - public_keys += f',{str(debug_public_key_0)}' - if debug_public_key_1.exists(): - public_keys += f',{str(debug_public_key_1)}' - - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../nrf/scripts/bootloader/provision.py\ - --s0-addr {cpunet_pm_app_address} --provision-addr {pm_provision_address}\ - --public-key-files {public_keys}\ - --output {build_dir}/provision.hex --num-counter-slots-version {num_ver_counter_slots}\ - --max-size {pm_partition_size_provision}' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/scripts/build/mergehex.py -o {build_dir}/b0n_container.hex\ - {build_dir}/{BLE5_CTR_HEX} {build_dir}/provision.hex' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/scripts/build/mergehex.py -o {build_dir}/{FINAL_BLE5_CTR_HEX}\ - --overlap=replace {build_dir}/{NET_CORE_APP_NAME}/b0n/zephyr/zephyr.hex {build_dir}/b0n_container.hex\ - {build_dir}/provision.hex {build_dir}/{BLE5_CTR_HEX} {build_dir}/signed_by_b0_ble5_ctr.hex' - - ret_val = os.system(os_cmd) - if ret_val: - raise Exception('python error: ' + str(ret_val)) - - # Replace built net_core - src_path = f'{build_dir}/{FINAL_BLE5_CTR_UPDATE_BIN}' - dst_path = f'{build_dir}/zephyr/net_core_app_update.bin' - shutil.copy(src_path, dst_path) - - src_path = f'{build_dir}/{FINAL_BLE5_CTR_HEX}' - dst_path = f'{build_dir}/zephyr/net_core_app_signed.hex' - shutil.copy(src_path, dst_path) - - # Generate merged_domains.hex - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/scripts/build/mergehex.py -o {build_dir}/zephyr/merged_domains.hex\ - {build_dir}/{FINAL_BLE5_CTR_HEX} {build_dir}/zephyr/merged.hex' - - ret_val = os.system(os_cmd) - # Generate dfu_application.zip - # set(generate_script_params - # "${app_core_binary_name}load_address=$" - # "${app_core_binary_name}image_index=0" - # "${app_core_binary_name}slot_index_primary=1" - # "${app_core_binary_name}slot_index_secondary=2" - # "${app_core_binary_name}version_MCUBOOT=${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION}" - # "${net_core_binary_name}image_index=1" - # "${net_core_binary_name}slot_index_primary=3" - # "${net_core_binary_name}slot_index_secondary=4" - # "${net_core_binary_name}load_address=$" - # "${net_core_binary_name}board=${CONFIG_DOMAIN_CPUNET_BOARD}" - # "${net_core_binary_name}version=${net_core_version}" - # "${net_core_binary_name}soc=${net_core_soc}" - # ) - os.remove(f'{build_dir}/zephyr/dfu_application.zip') - os_cmd = f'{sys.executable} {ZEPHYR_BASE}/../nrf/scripts/bootloader/generate_zip.py --bin-files\ - {build_dir}/zephyr/app_update.bin {build_dir}/zephyr/net_core_app_update.bin\ - --output {build_dir}/zephyr/dfu_application.zip --name nrf5340_audio\ - --meta-info-file {build_dir}/zephyr/zephyr.meta\ - app_update.binload_address={pm_app_app_address}\ - app_update.binimage_index=0\ - app_update.binslot_index_primary=1\ - app_update.binslot_index_secondary=2\ - app_update.binversion_MCUBOOT={image_version}\ - net_core_app_update.binimage_index=1\ - net_core_app_update.binslot_index_primary=3\ - net_core_app_update.binslot_index_secondary=4\ - net_core_app_update.binload_address={cpunet_pm_app_address}\ - net_core_app_update.binboard={net_core_app_binboard}\ - net_core_app_update.binversion={fw_info_firmware_version}\ - net_core_app_update.binsoc={net_soc_name}\ - type=application board={config_board} soc={soc_name}' - - ret_val = os.system(os_cmd) - - -def find_hex_name(options): - - in_path = Path(options.input_folder).resolve() - - # Add files only match pattern filename and 4 digits build number - pattern_found = sorted([ - file for file in in_path.iterdir()\ - if re.match(ORIG_BLE5_CTR_MIN_PATTERN if options.min_b0n else ORIG_BLE5_CTR_PATTERN, file.name)\ - is not None - ]) - - # Last hex file should be latest version. - return pattern_found[-1] - - -def __main(): - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description='This script sign and generate netcore hex and upgradable binary for the\ - nRF5340 Audio project on Windows and Linux', - allow_abbrev=False) - parser.add_argument('-i', '--input_file', type=str, - help='Input hex file name. Higher priority than -I') - parser.add_argument('-b', '--build_dir', required=True, type=str, - help='Build folder.') - parser.add_argument('-I', '--input_folder', type=str, - help='Input hex folder, let script choose filename automatically.\ - Lower priority than -i') - parser.add_argument('-m', '--min_b0n', default=False, action='store_true', - help='B0N use minimal. Only valid if -I is assigned') - options = parser.parse_args(args=sys.argv[1:]) - - if options.input_file is not None: - input_file_name = options.input_file - elif options.input_folder is not None: - input_file_name = find_hex_name(options) - print(f'input hex name {input_file_name}') - sign(input_file_name, options.build_dir) - - -if __name__ == '__main__': - __main() diff --git a/applications/nrf5340_audio/tools/buildprog/buildprog.py b/applications/nrf5340_audio/tools/buildprog/buildprog.py index 07bb1056988..51428d5a1d1 100644 --- a/applications/nrf5340_audio/tools/buildprog/buildprog.py +++ b/applications/nrf5340_audio/tools/buildprog/buildprog.py @@ -15,8 +15,8 @@ import json import subprocess import re -import glob import getpass +from pathlib import Path from colorama import Fore, Style from prettytable import PrettyTable from nrf5340_audio_dk_devices import ( @@ -27,10 +27,8 @@ AudioDevice, SelectFlags, Core, - Controller, ) from program import program_threads_run -from pathlib import Path BUILDPROG_FOLDER = Path(__file__).resolve().parent @@ -44,7 +42,6 @@ TARGET_BOARD_NRF5340_AUDIO_DK_APP_NAME = "nrf5340_audio_dk_nrf5340_cpuapp" TARGET_CORE_APP_FOLDER = NRF5340_AUDIO_FOLDER -TARGET_CORE_NET_FOLDER = NRF_FOLDER / "lib/bin/bt_ll_acs_nrf53/bin" TARGET_DEV_HEADSET_FOLDER = NRF5340_AUDIO_FOLDER / "build/dev_headset" TARGET_DEV_GATEWAY_FOLDER = NRF5340_AUDIO_FOLDER / "build/dev_gateway" @@ -87,9 +84,11 @@ def __print_dev_conf(device_list): print(table) -def __build_cmd_get(core: Core, device: AudioDevice, build: BuildType, pristine, controller: Controller, child_image, options): +def __build_cmd_get(core: Core, device: AudioDevice, build: BuildType, + pristine, child_image, options): if core == Core.app: - build_cmd = f"west build {TARGET_CORE_APP_FOLDER} -b {TARGET_BOARD_NRF5340_AUDIO_DK_APP_NAME}" + build_cmd = (f"west build {TARGET_CORE_APP_FOLDER} " + f"-b {TARGET_BOARD_NRF5340_AUDIO_DK_APP_NAME}") if device == AudioDevice.headset: device_flag = "-DCONFIG_AUDIO_DEV=1" dest_folder = TARGET_DEV_HEADSET_FOLDER @@ -98,6 +97,7 @@ def __build_cmd_get(core: Core, device: AudioDevice, build: BuildType, pristine, dest_folder = TARGET_DEV_GATEWAY_FOLDER else: raise Exception("Invalid device!") + if build == BuildType.debug: release_flag = "" dest_folder /= TARGET_DEBUG_FOLDER @@ -107,19 +107,12 @@ def __build_cmd_get(core: Core, device: AudioDevice, build: BuildType, pristine, else: raise Exception("Invalid build type!") - if options.mcuboot == 'internal': - device_flag += " -DCONFIG_AUDIO_DFU=1" - elif options.mcuboot == 'external': - device_flag += " -DCONFIG_AUDIO_DFU=2" - if options.min_b0n: - device_flag += " -DCONFIG_B0N_MINIMAL=y" - if options.controller == Controller.sdc: - device_flag += " -DCONFIG_BT_LL_ACS_NRF53=n" - if not child_image: - device_flag += " -DCONFIG_NCS_INCLUDE_RPMSG_CHILD_IMAGE=n" + if not child_image: + device_flag += " -DCONFIG_NCS_INCLUDE_RPMSG_CHILD_IMAGE=n" if options.nrf21540: device_flag += " -DSHIELD=nrf21540ek_fwd" + device_flag += " -Dhci_ipc_SHIELD=nrf21540ek" if options.custom_bt_name is not None and options.user_bt_name: raise Exception( @@ -142,7 +135,13 @@ def __build_cmd_get(core: Core, device: AudioDevice, build: BuildType, pristine, build_cmd += " -p" elif core == Core.net: - dest_folder = TARGET_CORE_NET_FOLDER + if build == BuildType.debug: + dest_folder /= TARGET_DEBUG_FOLDER + elif build == BuildType.release: + dest_folder /= TARGET_RELEASE_FOLDER + else: + raise Exception("Invalid build type!") + build_cmd = "" device_flag = "" release_flag = "" @@ -156,7 +155,6 @@ def __build_module(build_config, options): build_config.device, build_config.build, build_config.pristine, - build_config.controller, build_config.child_image, options, ) @@ -195,39 +193,11 @@ def __populate_hex_paths(dev, options, child_image): """Poplulate hex paths where relevant""" _, temp_dest_folder, _, _ = __build_cmd_get( - Core.app, dev.nrf5340_audio_dk_dev, options.build, options.pristine, options.controller, child_image, options + Core.app, dev.nrf5340_audio_dk_dev, options.build, options.pristine, child_image, options ) - dest_folder = temp_dest_folder - - if options.controller != Controller.acs_nrf53: - dev.hex_path_app = dest_folder / "zephyr/zephyr.hex" - dev.hex_path_net = dest_folder / "hci_ipc/zephyr/zephyr.hex" - return - - if dev.core_app_programmed == SelectFlags.TBD: - if options.mcuboot != '': - dev.hex_path_app = dest_folder / "zephyr/merged.hex" - else: - dev.hex_path_app = dest_folder / "zephyr/zephyr.hex" - - if dev.core_net_programmed == SelectFlags.TBD: - - hex_files_found = 0 - for hex_path in glob.glob(str(TARGET_CORE_NET_FOLDER) + "/ble5-ctr-rpmsg_????.hex"): - dev.hex_path_net = hex_path - hex_files_found += 1 - - if options.mcuboot != '': - dev.hex_path_net = dest_folder / "zephyr/net_core_app_signed.hex" - else: - dest_folder = TARGET_CORE_NET_FOLDER - - if hex_files_found != 1: - raise Exception( - f"Found zero or multiple NET hex files in folder: {dest_folder}") - else: - print(f"Using NET hex: {dev.hex_path_net} for {dev}") + dev.hex_path_app = temp_dest_folder / "zephyr/zephyr.hex" + dev.hex_path_net = temp_dest_folder / "hci_ipc/zephyr/zephyr.hex" def __finish(device_list): @@ -244,8 +214,9 @@ def __main(): "This script builds and programs the nRF5340 " "Audio project on Windows and Linux" ), - epilog=("If there exists an environmental variable called \"AUDIO_KIT_SERIAL_NUMBERS_JSON\" which contains" - "the location of a json file, the program will use this file as a substitute for nrf5340_audio_dk_devices.json"), + epilog=("If there exists an environmental variable called \"AUDIO_KIT_SERIAL_NUMBERS_JSON\"" + "which contains the location of a json file," + "the program will use this file as a substitute for nrf5340_audio_dk_devices.json"), allow_abbrev=False ) parser.add_argument( @@ -300,8 +271,7 @@ def __main(): action="store_true", dest="sequential_prog", default=False, - help="Run nrfjprog sequentially instead of in \ - parallel", + help="Run nrfjprog sequentially instead of in parallel", ) parser.add_argument( "-f", @@ -311,33 +281,6 @@ def __main(): default=False, help="Recover device if programming fails", ) - parser.add_argument( - # Experimental argument - "--ctlr", - type=str, - choices=[i.value for i in Controller], - dest="controller", - default=Controller.acs_nrf53.value, - help=argparse.SUPPRESS, - ) - # DFU relative option - parser.add_argument( - "-M", - "--min_b0n", - dest="min_b0n", - action='store_true', - default=False, - help="net core bootloader use minimal size build. Only for controller: " + - Controller.acs_nrf53, - ) - parser.add_argument( - "-m", - "--mcuboot", - required=("-M" in sys.argv or "--min_b0n" in sys.argv), - choices=["external", "internal"], - default='', - help="MCUBOOT with external, internal flash. Only for controller: " + Controller.acs_nrf53, - ) parser.add_argument( "--nrf21540", action="store_true", @@ -359,18 +302,12 @@ def __main(): action="store_true", dest="user_bt_name", default=False, - help="Set to generate a user specific Bluetooth device name. Note that this will put the computer user name on air in clear text", + help="Set to generate a user specific Bluetooth device name.\ + Note that this will put the computer user name on air in clear text", ) options = parser.parse_args(args=sys.argv[1:]) - if options.controller != Controller.acs_nrf53: - print(Fore.YELLOW + - "Experimental app - controller combination" + Style.RESET_ALL) - if options.nrf21540 or options.mcuboot != '' or options.min_b0n: - raise Exception("nrf21540 or DFU arguments only accepted when using controller: " + - Controller.acs_nrf53 + ". Please use standard tools.") - # Post processing for Enums if options.core is None: cores = [] @@ -411,7 +348,6 @@ def __main(): cores=cores, devices=devices, _only_reboot=options.only_reboot, - controller=options.controller, ) for dev in dev_arr ] @@ -422,8 +358,7 @@ def __main(): # Reboot step start if options.only_reboot == SelectFlags.TBD: - program_threads_run(device_list, options.mcuboot, - sequential=options.sequential_prog) + program_threads_run(device_list, sequential=options.sequential_prog) __finish(device_list) # Reboot step finished @@ -444,7 +379,6 @@ def __main(): device=AudioDevice.headset, pristine=options.pristine, build=options.build, - controller=options.controller, child_image=child_image, ) ) @@ -455,7 +389,6 @@ def __main(): device=AudioDevice.gateway, pristine=options.pristine, build=options.build, - controller=options.controller, child_image=child_image, ) ) @@ -473,8 +406,7 @@ def __main(): for dev in device_list: if dev.snr_connected: __populate_hex_paths(dev, options, child_image) - program_threads_run(device_list, options.mcuboot, - sequential=options.sequential_prog) + program_threads_run(device_list, sequential=options.sequential_prog) # Program step finished diff --git a/applications/nrf5340_audio/tools/buildprog/nrf5340_audio_dk_devices.py b/applications/nrf5340_audio/tools/buildprog/nrf5340_audio_dk_devices.py index 7d8eb296c78..3da7ec4c024 100644 --- a/applications/nrf5340_audio/tools/buildprog/nrf5340_audio_dk_devices.py +++ b/applications/nrf5340_audio/tools/buildprog/nrf5340_audio_dk_devices.py @@ -15,7 +15,6 @@ class SelectFlags(str, Enum): """Holds the available status flags""" - NOT = "Not selected" TBD = "Selected" DONE = "Done" @@ -23,34 +22,32 @@ class SelectFlags(str, Enum): class Core(str, Enum): + """SoC core""" app = "app" net = "network" both = "both" class AudioDevice(str, Enum): + """Audio device""" headset = "headset" gateway = "gateway" both = "both" class BuildType(str, Enum): + """Release or debug build""" release = "release" debug = "debug" class Channel(Enum): - # Value represents UICR channel + """Left or right Value represents UICR channel""" left = 0 right = 1 NA = auto() -class Controller(str, Enum): - acs_nrf53 = "ACS_nRF53" - sdc = "SDC" - - @dataclass class DeviceConf: """This config is populated according to connected SEGGER serial numbers @@ -66,7 +63,6 @@ class DeviceConf: cores: InitVar[List[Core]] devices: InitVar[List[AudioDevice]] _only_reboot: InitVar[SelectFlags] - controller: InitVar[List[Controller]] # Post init variables only_reboot: SelectFlags = field(init=False, default=SelectFlags.NOT) hex_path_app: Path = field(init=False, default=None) @@ -77,11 +73,10 @@ class DeviceConf: init=False, default=SelectFlags.NOT) def __post_init__( - self, cores: List[Core], devices: List[AudioDevice], _only_reboot: SelectFlags, controller: Controller, + self, cores: List[Core], devices: List[AudioDevice], _only_reboot: SelectFlags, ): device_selected = self.nrf5340_audio_dk_dev in devices self.only_reboot = _only_reboot if device_selected else SelectFlags.NOT - self.controller = controller if self.only_reboot == SelectFlags.TBD: return @@ -91,10 +86,10 @@ def __post_init__( self.core_net_programmed = SelectFlags.TBD def __str__(self): - str = f"{self.nrf5340_audio_dk_snr} {self.nrf5340_audio_dk_dev.name}" + result = f"{self.nrf5340_audio_dk_snr} {self.nrf5340_audio_dk_dev.name}" if self.nrf5340_audio_dk_dev == AudioDevice.headset: - str += f" {self.channel.name}" - return str + result += f" {self.channel.name}" + return result @dataclass @@ -105,5 +100,4 @@ class BuildConf: device: AudioDevice build: BuildType pristine: bool - controller: Controller child_image: bool diff --git a/applications/nrf5340_audio/tools/buildprog/program.py b/applications/nrf5340_audio/tools/buildprog/program.py index a5ca7ac7dc1..a75b80c4053 100644 --- a/applications/nrf5340_audio/tools/buildprog/program.py +++ b/applications/nrf5340_audio/tools/buildprog/program.py @@ -9,16 +9,17 @@ from threading import Thread from os import system, path from typing import List -from nrf5340_audio_dk_devices import DeviceConf, SelectFlags, AudioDevice, Controller +from nrf5340_audio_dk_devices import DeviceConf, SelectFlags, AudioDevice MEM_ADDR_UICR_SNR = 0x00FF80F0 MEM_ADDR_UICR_CH = 0x00FF80F4 -def __populate_UICR(dev): +def __populate_uicr(dev): """Program UICR in device with information from JSON file""" if dev.nrf5340_audio_dk_dev == AudioDevice.headset: - cmd = f"nrfjprog --memwr {MEM_ADDR_UICR_CH} --val {dev.channel.value} --snr {dev.nrf5340_audio_dk_snr}" + cmd = (f"nrfjprog --memwr {MEM_ADDR_UICR_CH} --val {dev.channel.value} " + f"--snr {dev.nrf5340_audio_dk_snr}") # Write channel information to UICR print("Programming UICR") ret_val = system(cmd) @@ -26,7 +27,8 @@ def __populate_UICR(dev): if ret_val: return False - cmd = f"nrfjprog --memwr {MEM_ADDR_UICR_SNR} --val {dev.nrf5340_audio_dk_snr} --snr {dev.nrf5340_audio_dk_snr}" + cmd = (f"nrfjprog --memwr {MEM_ADDR_UICR_SNR} --val {dev.nrf5340_audio_dk_snr} " + f"--snr {dev.nrf5340_audio_dk_snr}") # Write segger nr to UICR ret_val = system(cmd) @@ -36,18 +38,15 @@ def __populate_UICR(dev): return True -def _program_cores(dev: DeviceConf, mcuboot_type) -> int: +def _program_cores(dev: DeviceConf) -> int: if dev.core_net_programmed == SelectFlags.TBD: if not path.isfile(dev.hex_path_net): - if dev.controller == Controller.sdc: - print( - "Controller: SDC. NET core hex not found. Built as APP core child image.") - if dev.controller == Controller.acs_nrf53: - print("Controller: acs_nrf53. NET core hex not found.") + print("NET core hex not found. Built as APP core child image.") return 1 print(f"Programming net core on: {dev}") - cmd = f"nrfjprog --program {dev.hex_path_net} -f NRF53 -q --snr {dev.nrf5340_audio_dk_snr} --sectorerase --coprocessor CP_NETWORK" + cmd = (f"nrfjprog --program {dev.hex_path_net} -f NRF53 -q " + f"--snr {dev.nrf5340_audio_dk_snr} --sectorerase --coprocessor CP_NETWORK") ret_val = system(cmd) if ret_val != 0: if not dev.recover_on_fail: @@ -58,7 +57,8 @@ def _program_cores(dev: DeviceConf, mcuboot_type) -> int: if dev.core_app_programmed == SelectFlags.TBD: print(f"Programming app core on: {dev}") - cmd = f"nrfjprog --program {dev.hex_path_app} -f NRF53 -q --snr {dev.nrf5340_audio_dk_snr} --chiperase --coprocessor CP_APPLICATION" + cmd = (f"nrfjprog --program {dev.hex_path_app} -f NRF53 -q " + f"--snr {dev.nrf5340_audio_dk_snr} --chiperase --coprocessor CP_APPLICATION") ret_val = system(cmd) if ret_val != 0: if not dev.recover_on_fail: @@ -67,17 +67,13 @@ def _program_cores(dev: DeviceConf, mcuboot_type) -> int: else: dev.core_app_programmed = SelectFlags.DONE # Populate UICR data matching the JSON file - if not __populate_UICR(dev): + if not __populate_uicr(dev): dev.core_app_programmed = SelectFlags.FAIL return 1 if dev.core_net_programmed != SelectFlags.NOT or dev.core_app_programmed != SelectFlags.NOT: - if mcuboot_type == 'external': - print(f"Hard resetting {dev}") - cmd = f"nrfjprog -p --snr {dev.nrf5340_audio_dk_snr}" - else: - print(f"Resetting {dev}") - cmd = f"nrfjprog -r --snr {dev.nrf5340_audio_dk_snr}" + print(f"Resetting {dev}") + cmd = f"nrfjprog -r --snr {dev.nrf5340_audio_dk_snr}" ret_val = system(cmd) if ret_val != 0: return ret_val @@ -99,7 +95,7 @@ def _recover(dev: DeviceConf): dev.core_app_programmed = SelectFlags.FAIL -def __program_thread(dev: DeviceConf, mcuboot_type): +def __program_thread(dev: DeviceConf): if dev.only_reboot == SelectFlags.TBD: print(f"Resetting {dev}") cmd = f"nrfjprog -r --snr {dev.nrf5340_audio_dk_snr}" @@ -107,13 +103,13 @@ def __program_thread(dev: DeviceConf, mcuboot_type): dev.only_reboot = SelectFlags.FAIL if ret_val else SelectFlags.DONE return - return_code = _program_cores(dev, mcuboot_type) + return_code = _program_cores(dev) if return_code != 0 and dev.recover_on_fail: _recover(dev) - _program_cores(dev, mcuboot_type) + _program_cores(dev) -def program_threads_run(devices_list: List[DeviceConf], mcuboot_type, sequential: bool = False): +def program_threads_run(devices_list: List[DeviceConf], sequential: bool = False): """Program devices in parallel""" threads = [] # First program net cores if applicable @@ -123,7 +119,7 @@ def program_threads_run(devices_list: List[DeviceConf], mcuboot_type, sequential dev.core_app_programmed = SelectFlags.NOT dev.core_net_programmed = SelectFlags.NOT continue - thread = Thread(target=__program_thread, args=(dev, mcuboot_type)) + thread = Thread(target=__program_thread, args=(dev,)) threads.append(thread) thread.start() if sequential: diff --git a/applications/nrf5340_audio/unicast_client/CMakeLists.txt b/applications/nrf5340_audio/unicast_client/CMakeLists.txt new file mode 100644 index 00000000000..5c48ca62e4c --- /dev/null +++ b/applications/nrf5340_audio/unicast_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) diff --git a/applications/nrf5340_audio/unicast_client/Kconfig.defaults b/applications/nrf5340_audio/unicast_client/Kconfig.defaults new file mode 100644 index 00000000000..9e69d740a2c --- /dev/null +++ b/applications/nrf5340_audio/unicast_client/Kconfig.defaults @@ -0,0 +1,71 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config UTF8 + default y + +## ACL related configs ## +config BT_MAX_CONN + default 2 + +# Generic Audio Source - 0x0880 +config BT_DEVICE_APPEARANCE + default 2176 + +config BT_MAX_PAIRED + default 2 + +config BT_GATT_DYNAMIC_DB + default y + + +## ISO related configs ## +config BT_ISO_MAX_CHAN + default 4 + +config BT_BAP_UNICAST_CLIENT + default y + +config BT_ISO_TX_BUF_COUNT + default 2 + +config BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT + default 4 + +config BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT + default 2 + +config BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT + default 2 + +config BT_VCP_VOL_CTLR + default y + +config BT_MCS + default y + +config BT_MPL + default y + +config MCTL + default y + +config MCTL_LOCAL_PLAYER_CONTROL + default y + +config MCTL_LOCAL_PLAYER_REMOTE_CONTROL + default y + + +## LC3 related configs ## +config LC3_BITRATE + default BT_AUDIO_BITRATE_UNICAST_SINK + +config LC3_ENC_CHAN_MAX + default 2 + +config LC3_DEC_CHAN_MAX + default 1 diff --git a/applications/nrf5340_audio/unicast_client/README.rst b/applications/nrf5340_audio/unicast_client/README.rst new file mode 100644 index 00000000000..286c52fd830 --- /dev/null +++ b/applications/nrf5340_audio/unicast_client/README.rst @@ -0,0 +1,144 @@ +.. _nrf53_audio_unicast_client_app: + +nRF5340 Audio: Unicast client +############################# + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio unicast client application implements the :ref:`CIS gateway mode `. + +In this mode, one Connected Isochronous Group (CIG) can be used with two Connected Isochronous Streams (CIS). +Transmitting unidirectional or transceiving bidirectional audio happens using CIG and CIS. + +The following limitations apply to this application: + +* One CIG with two CIS. +* Audio input: USB or I2S (Line in or using Pulse Density Modulation). +* Audio output: USB or I2S/Analog headset output. +* Configuration: 16 bit, several bit rates ranging from 32 kbps to 124 kbps. + +.. _nrf53_audio_unicast_client_app_requirements: + +Requirements +************ + +The application shares the :ref:`requirements common to all nRF5340 Audio application `. + +.. _nrf53_audio_unicast_client_app_ui: + +User interface +************** + +Most of the user interface mappings are common across all nRF5340 Audio applications. +See the :ref:`nrf53_audio_app_ui` page for detailed overview. + +This application uses specific mapping for the following user interface elements: + +* Long-pressed on the unicast client device during startup: + + * **BTN5** - Clears the previously stored bonding information. + +* Pressed on the unicast client device during playback: + + * **PLAY/PAUSE** - Starts or pauses the playback of the stream. + * **VOL-** - Turns the playback volume down (and unmutes). + * **VOL+** - Turns the playback volume up (and unmutes). + * **BTN 4** - Sends a test tone generated on the device. Use this tone to check the synchronization of headsets. + * **BTN5** - Mutes the playback volume (and unmutes). + +* **LED1** - Blinking blue - Kit is streaming audio to a headset. +* **RGB** - Solid green - The device is programmed as the gateway. + +.. _nrf53_audio_unicast_client_app_configuration: + +Configuration +************* + +By default, if you have not made any changes to :file:`.conf` files at :file:`applications/nrf5340_audio/`, the nRF5340 build script tries to build the CIS applications in the CIS unidirectional mode. +To switch to the bidirectional mode, see :ref:`nrf53_audio_app_configuration_select_bidirectional`. + +For other configuration options, see :ref:`nrf53_audio_app_configuration` and :ref:`nrf53_audio_app_fota`. + +For information about how to configure applications in the |NCS|, see :ref:`configure_application`. + +.. _nrf53_audio_unicast_client_app_building: + +Building and running +******************** + +This application can be found under :file:`applications/nrf5340_audio/unicast_client` in the nRF Connect SDK folder structure, but it uses :file:`.conf` files at :file:`applications/nrf5340_audio/`. + +The nRF5340 Audio DK comes preprogrammed with basic firmware that indicates if the kit is functional. +See :ref:`nrf53_audio_app_dk_testing_out_of_the_box` for more information. + +To build the application, see :ref:`nrf53_audio_app_building`. + +.. _nrf53_audio_unicast_client_app_testing: + +Testing +******* + +After building and programming the application, you can test the default CIS gateway mode using one unicast client device and at least one CIS headset device. +The recommended approach is to use another nRF5340 Audio DK programmed with the :ref:`unicast server application `, but you can also use an external CIS headset device. + +.. note:: + |nrf5340_audio_external_devices_note| + +The following testing scenario assumes you are using USB as the audio source on the gateway. +This is the default setting. + +Complete the following steps to test the unidirectional CIS mode for one gateway and at least one headset device: + +1. Make sure that the development kits are still plugged into the USB ports and are turned on. + + .. note:: + |usb_known_issues| + + **LED3** starts blinking green on every device to indicate the ongoing CPU activity on the application core. +#. Wait for the **LED1** on the gateway to start blinking blue. + This happens shortly after programming the development kit and indicates that the gateway device is connected to at least one headset and ready to send data. +#. Search the list of audio devices listed in the sound settings of your operating system for *nRF5340 USB Audio* (gateway) and select it as the output device. +#. Connect headphones to the **HEADPHONE** audio jack on the headset device. +#. Start audio playback on your PC from any source. +#. Wait for **LED1** to blink blue on the headset. + When they do, the audio stream has started on the headset. + + .. note:: + The audio outputs only to the left channel of the audio jack, even if the given headset is configured as the right headset. + This is because of the mono hardware codec chip used on the development kits. + If you want to play stereo sound using one development kit, you must connect an external hardware codec chip that supports stereo. + +#. Wait for **LED2** to light up solid green on the headsets to indicate that the audio synchronization is achieved. +#. Press the **VOL-** button on the gateway. + The playback volume decreases for the headset. +#. Press the **PLAY/PAUSE** button on any one of the devices. + The playback stops for the headset and the streaming state for all devices is set to paused. +#. Press the **BTN 4** button on the gateway multiple times. + For each button press, the audio stream playback is stopped and the gateway sends a test tone to the headset. + These tones can be used as audio cues to check the synchronization between two headsets. + +For other testing options, refer to :ref:`nrf53_audio_unicast_client_app_ui`. + +After the kits have paired for the first time, they are now bonded. +This means the Long-Term Key (LTK) is stored on each side, and that the kits will only connect to each other unless the bonding information is cleared. +To clear the bonding information, press and hold **BTN 5** during boot or reprogram all the development kits. + +When you finish testing, power off the nRF5340 Audio development kits by switching the power switch from On to Off. + +.. _nrf53_audio_unicast_client_app_testing_steps_cis_walkie_talkie: + +Testing the walkie-talkie demo +============================== + +Testing the walkie-talkie demo is identical to the default testing procedure, except for the following differences: + +* You must enable the Kconfig option mentioned in :ref:`nrf53_audio_app_configuration_enable_walkie_talkie` before building the application. +* Instead of controlling the playback, you can speak through the PDM microphones. + The line is open all the time, no need to press any buttons to talk, but the volume control works as in the default testing procedure. + +Dependencies +************ + +For the list of dependencies, check the application's source files. diff --git a/applications/nrf5340_audio/unicast_client/main.c b/applications/nrf5340_audio/unicast_client/main.c new file mode 100644 index 00000000000..7895e5671f7 --- /dev/null +++ b/applications/nrf5340_audio/unicast_client/main.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "streamctrl.h" + +#include + +#include "nrf5340_audio_common.h" +#include "nrf5340_audio_dk.h" +#include "led.h" +#include "button_assignments.h" +#include "macros_common.h" +#include "audio_system.h" +#include "button_handler.h" +#include "bt_le_audio_tx.h" +#include "bt_mgmt.h" +#include "bt_rendering_and_capture.h" +#include "bt_content_ctrl.h" +#include "unicast_client.h" +#include "le_audio_rx.h" + +#include +LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL); + +static enum stream_state strm_state = STATE_PAUSED; + +ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); +ZBUS_SUBSCRIBER_DEFINE(content_control_evt_sub, CONFIG_CONTENT_CONTROL_MSG_SUB_QUEUE_SIZE); + +ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); + +ZBUS_CHAN_DECLARE(button_chan); +ZBUS_CHAN_DECLARE(le_audio_chan); +ZBUS_CHAN_DECLARE(bt_mgmt_chan); +ZBUS_CHAN_DECLARE(cont_media_chan); +ZBUS_CHAN_DECLARE(sdu_ref_chan); + +ZBUS_OBS_DECLARE(sdu_ref_msg_listen); + +static struct k_thread button_msg_sub_thread_data; +static struct k_thread le_audio_msg_sub_thread_data; +static struct k_thread content_control_msg_sub_thread_data; + +static k_tid_t button_msg_sub_thread_id; +static k_tid_t le_audio_msg_sub_thread_id; +static k_tid_t content_control_thread_id; + +K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); +K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); +K_THREAD_STACK_DEFINE(content_control_msg_sub_thread_stack, + CONFIG_CONTENT_CONTROL_MSG_SUB_STACK_SIZE); + +/* Function for handling all stream state changes */ +static void stream_state_set(enum stream_state stream_state_new) +{ + strm_state = stream_state_new; +} + +static void content_control_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + + while (1) { + ret = zbus_sub_wait(&content_control_evt_sub, &chan, K_FOREVER); + ERR_CHK(ret); + + struct content_control_msg msg; + + ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); + ERR_CHK(ret); + + switch (msg.event) { + case MEDIA_START: + unicast_client_start(); + break; + + case MEDIA_STOP: + unicast_client_stop(); + break; + + default: + LOG_WRN("Unhandled event from content ctrl: %d", msg.event); + break; + } + + STACK_USAGE_PRINT("content_ctrl_msg_thread", &content_control_msg_sub_thread); + } +} + +/** + * @brief Handle button activity. + */ +static void button_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + + while (1) { + ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); + ERR_CHK(ret); + + struct button_msg msg; + + ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); + ERR_CHK(ret); + + LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, + msg.button_action); + + if (msg.button_action != BUTTON_PRESS) { + LOG_WRN("Unhandled button action"); + return; + } + + switch (msg.button_pin) { + case BUTTON_PLAY_PAUSE: + if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { + LOG_WRN("Play/pause not supported in walkie-talkie mode"); + break; + } + + if (strm_state == STATE_STREAMING) { + ret = bt_content_ctrl_stop(NULL); + if (ret) { + LOG_WRN("Could not stop: %d", ret); + } + + } else if (strm_state == STATE_PAUSED) { + ret = bt_content_ctrl_start(NULL); + if (ret) { + LOG_WRN("Could not start: %d", ret); + } + + } else { + LOG_WRN("In invalid state: %d", strm_state); + } + + break; + + case BUTTON_VOLUME_UP: + ret = bt_r_and_c_volume_up(); + if (ret) { + LOG_WRN("Failed to increase volume: %d", ret); + } + + break; + + case BUTTON_VOLUME_DOWN: + ret = bt_r_and_c_volume_down(); + if (ret) { + LOG_WRN("Failed to decrease volume: %d", ret); + } + + break; + + case BUTTON_4: + if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { + if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { + LOG_DBG("Test tone is disabled in walkie-talkie mode"); + break; + } + + if (strm_state != STATE_STREAMING) { + LOG_WRN("Not in streaming state"); + break; + } + + ret = audio_system_encode_test_tone_step(); + if (ret) { + LOG_WRN("Failed to play test tone, ret: %d", ret); + } + + break; + } + + break; + + case BUTTON_5: + if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { + ret = bt_r_and_c_volume_mute(false); + if (ret) { + LOG_WRN("Failed to mute, ret: %d", ret); + } + + break; + } + + break; + + default: + LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); + } + + STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); + } +} + +/** + * @brief Handle Bluetooth LE audio events. + */ +static void le_audio_msg_sub_thread(void) +{ + int ret; + uint32_t bitrate_bps; + uint32_t sampling_rate_hz; + const struct zbus_channel *chan; + + while (1) { + struct le_audio_msg msg; + + ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); + ERR_CHK(ret); + + LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); + + switch (msg.event) { + case LE_AUDIO_EVT_STREAMING: + LOG_DBG("LE audio evt streaming"); + + if (strm_state == STATE_STREAMING) { + LOG_DBG("Got streaming event in streaming state"); + break; + } + + if (msg.dir == BT_AUDIO_DIR_SINK) { + audio_system_encoder_start(); + } + + audio_system_start(); + stream_state_set(STATE_STREAMING); + + ret = led_blink(LED_APP_1_BLUE); + ERR_CHK(ret); + break; + + case LE_AUDIO_EVT_NOT_STREAMING: + LOG_DBG("LE audio evt not_streaming"); + + if (strm_state == STATE_PAUSED) { + LOG_DBG("Got not_streaming event in paused state"); + break; + } + + if (msg.dir == BT_AUDIO_DIR_SINK) { + audio_system_encoder_stop(); + } + + stream_state_set(STATE_PAUSED); + audio_system_stop(); + + ret = led_on(LED_APP_1_BLUE); + ERR_CHK(ret); + break; + + case LE_AUDIO_EVT_NO_VALID_CFG: + LOG_WRN("No valid configurations found or CIS establishment failed, will " + "disconnect"); + + ret = bt_mgmt_conn_disconnect(msg.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (ret) { + LOG_ERR("Failed to disconnect: %d", ret); + } + + break; + + case LE_AUDIO_EVT_CONFIG_RECEIVED: + LOG_DBG("LE audio config received"); + + ret = unicast_client_config_get(msg.conn, msg.dir, &bitrate_bps, + &sampling_rate_hz); + if (ret) { + LOG_WRN("Failed to get config: %d", ret); + break; + } + + LOG_DBG("\tSampling rate: %d Hz", sampling_rate_hz); + LOG_DBG("\tBitrate (compressed): %d bps", bitrate_bps); + + if (msg.dir == BT_AUDIO_DIR_SINK) { + ret = audio_system_config_set(sampling_rate_hz, bitrate_bps, + VALUE_NOT_SET); + ERR_CHK(ret); + } else if (msg.dir == BT_AUDIO_DIR_SOURCE) { + ret = audio_system_config_set(VALUE_NOT_SET, VALUE_NOT_SET, + sampling_rate_hz); + ERR_CHK(ret); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); + break; + } + + STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); + } +} + +/** + * @brief Zbus listener to receive events from bt_mgmt. + * + * @param[in] chan Zbus channel. + * + * @note Will in most cases be called from BT_RX context, + * so there should not be too much processing done here. + */ +static void bt_mgmt_evt_handler(const struct zbus_channel *chan) +{ + int ret; + const struct bt_mgmt_msg *msg; + + msg = zbus_chan_const_msg(chan); + + switch (msg->event) { + case BT_MGMT_CONNECTED: + LOG_INF("Device connected"); + break; + + case BT_MGMT_SECURITY_CHANGED: + LOG_INF("Security changed"); + + ret = bt_r_and_c_discover(msg->conn); + if (ret) { + LOG_WRN("Failed to discover rendering services"); + } + + if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL)) { + ret = unicast_client_discover(msg->conn, UNICAST_SERVER_BIDIR); + } else { + ret = unicast_client_discover(msg->conn, UNICAST_SERVER_SINK); + } + + if (ret) { + LOG_ERR("Failed to handle unicast client discover: %d", ret); + } + + break; + + case BT_MGMT_DISCONNECTED: + LOG_INF("Device disconnected"); + + unicast_client_conn_disconnected(msg->conn); + break; + + default: + LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); + break; + } +} + +ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); + +/** + * @brief Create zbus subscriber threads. + * + * @return 0 for success, error otherwise. + */ +static int zbus_subscribers_create(void) +{ + int ret; + + button_msg_sub_thread_id = k_thread_create( + &button_msg_sub_thread_data, button_msg_sub_thread_stack, + CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create button_msg thread"); + return ret; + } + + le_audio_msg_sub_thread_id = k_thread_create( + &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, + CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create le_audio_msg thread"); + return ret; + } + + content_control_thread_id = k_thread_create( + &content_control_msg_sub_thread_data, content_control_msg_sub_thread_stack, + CONFIG_CONTENT_CONTROL_MSG_SUB_STACK_SIZE, + (k_thread_entry_t)content_control_msg_sub_thread, NULL, NULL, NULL, + K_PRIO_PREEMPT(CONFIG_CONTENT_CONTROL_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(content_control_thread_id, "CONTENT_CONTROL_MSG_SUB"); + if (ret) { + return ret; + } + + ret = zbus_chan_add_obs(&sdu_ref_chan, &sdu_ref_msg_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add timestamp listener"); + return ret; + } + + return 0; +} + +/** + * @brief Link zbus producers and observers. + * + * @return 0 for success, error otherwise. + */ +static int zbus_link_producers_observers(void) +{ + int ret; + + if (!IS_ENABLED(CONFIG_ZBUS)) { + return -ENOTSUP; + } + + ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add button sub"); + return ret; + } + + ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add le_audio sub"); + return ret; + } + + ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add bt_mgmt listener"); + return ret; + } + + ret = zbus_chan_add_obs(&cont_media_chan, &content_control_evt_sub, + ZBUS_ADD_OBS_TIMEOUT_MS); + + return 0; +} + +uint8_t stream_state_get(void) +{ + return strm_state; +} + +void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) +{ + int ret; + static int prev_ret; + + struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; + + if (strm_state == STATE_STREAMING) { + ret = unicast_client_send(enc_audio); + + if (ret != 0 && ret != prev_ret) { + if (ret == -ECANCELED) { + LOG_WRN("Sending operation cancelled"); + } else { + LOG_WRN("Problem with sending LE audio data, ret: %d", ret); + } + } + + prev_ret = ret; + } +} + +int main(void) +{ + int ret; + + LOG_DBG("nRF5340 APP core started"); + + ret = nrf5340_audio_dk_init(); + ERR_CHK(ret); + + ret = nrf5340_audio_common_init(); + ERR_CHK(ret); + + ret = zbus_subscribers_create(); + ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); + + ret = zbus_link_producers_observers(); + ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); + + ret = le_audio_rx_init(); + ERR_CHK(ret); + + ret = bt_r_and_c_init(); + ERR_CHK(ret); + + ret = bt_content_ctrl_init(); + ERR_CHK(ret); + + ret = unicast_client_enable(le_audio_rx_data_handler); + ERR_CHK(ret); + + ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, CONFIG_BT_DEVICE_NAME, + BRDCAST_ID_NOT_USED); + if (ret) { + LOG_ERR("Failed to start scanning"); + return ret; + } + + return 0; +} diff --git a/applications/nrf5340_audio/unicast_server/CMakeLists.txt b/applications/nrf5340_audio/unicast_server/CMakeLists.txt new file mode 100644 index 00000000000..5c48ca62e4c --- /dev/null +++ b/applications/nrf5340_audio/unicast_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) diff --git a/applications/nrf5340_audio/unicast_server/Kconfig.defaults b/applications/nrf5340_audio/unicast_server/Kconfig.defaults new file mode 100644 index 00000000000..eccf06f9662 --- /dev/null +++ b/applications/nrf5340_audio/unicast_server/Kconfig.defaults @@ -0,0 +1,82 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +## ACL related configs ## +config BT_MAX_CONN + default 4 + +config BT_MAX_PAIRED + default 4 + +config BT_PERIPHERAL + default y + +config BT_GATT_AUTO_RESUBSCRIBE + default n + +config BT_GATT_AUTO_SEC_REQ + default n + + +## ISO related configs ## +config BT_BAP_UNICAST_SERVER + default y + +config BT_ISO_MAX_CHAN + default 2 + +# Earbud - 0x0941 +config BT_DEVICE_APPEARANCE + default 2369 + +config BT_GAP_PERIPHERAL_PREF_PARAMS + default n + +config BT_ASCS_ASE_SNK_COUNT + default 1 + +config BT_ASCS_ASE_SRC_COUNT + default 1 if STREAM_BIDIRECTIONAL + default 0 if !STREAM_BIDIRECTIONAL + +config BT_VCP_VOL_REND + default y + +config BT_MCC + default y + +config BT_MCC_READ_MEDIA_STATE + default y + +config BT_MCC_SET_MEDIA_CONTROL_POINT + default y + +# For fixing compatibility issue with Android 14 +config BT_PAC_SNK_NOTIFIABLE + default y + +config BT_CSIP_SET_MEMBER + default y + +config BT_CAP_ACCEPTOR + default y + +config BT_CAP_ACCEPTOR_SET_MEMBER + default y + +config BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + default 25 + + +## LC3 related configs ## +config LC3_BITRATE + default BT_AUDIO_BITRATE_UNICAST_SRC + +config LC3_ENC_CHAN_MAX + default 1 + +config LC3_DEC_CHAN_MAX + default 1 diff --git a/applications/nrf5340_audio/unicast_server/README.rst b/applications/nrf5340_audio/unicast_server/README.rst new file mode 100644 index 00000000000..4b253de2041 --- /dev/null +++ b/applications/nrf5340_audio/unicast_server/README.rst @@ -0,0 +1,150 @@ +.. _nrf53_audio_unicast_server_app: + +nRF5340 Audio: Unicast server +############################# + +.. contents:: + :local: + :depth: 2 + +The nRF5340 Audio unicast server application implements the :ref:`CIS headset mode `. + +In this mode, one Connected Isochronous Group (CIG) can be used with two Connected Isochronous Streams (CIS). +Receiving unidirectional or transceiving bidirectional audio happens using CIG and CIS. +In addition, Coordinated Set Identification Service (CSIS) is implemented on the server side. + +The following limitations apply to this application: + +* One CIG, one of the two CIS streams (selectable). +* Audio output: I2S/Analog headset output. +* Audio input: PDM microphone over I2S. +* Configuration: 16 bit, several bit rates ranging from 32 kbps to 124 kbps. + +.. _nrf53_audio_unicast_server_app_requirements: + +Requirements +************ + +The application shares the :ref:`requirements common to all nRF5340 Audio application `. + +.. _nrf53_audio_unicast_server_app_ui: + +User interface +************** + +Most of the user interface mappings are common across all nRF5340 Audio applications. +See the :ref:`nrf53_audio_app_ui` page for detailed overview. + +This application uses specific mapping for the following user interface elements: + +* Long-pressed on the unicast server device during startup: + + * **VOL-** - Changes the headset to the left channel one. + * **VOL+** - Changes the headset to the right channel one. + * **BTN5** - Clears the previously stored bonding information. + +* Pressed on the unicast server device during playback: + + * **PLAY/PAUSE** - Starts or pauses the playback of the stream. + * **VOL-** - Turns the playback volume down. + * **VOL+** - Turns the playback volume up. + * **BTN5** - Mutes the playback volume (and unmutes). + +* **LED1** - Blinking blue - Kits have started streaming audio. +* **LED2** - Solid green - Sync achieved (both drift and presentation compensation are in the ``LOCKED`` state). +* **RGB**: + + * Solid blue - The device is programmed as the left headset. + * Solid magenta - The device is programmed as the right headset. + +.. _nrf53_audio_unicast_server_app_configuration: + +Configuration +************* + +By default, if you have not made any changes to :file:`.conf` files at :file:`applications/nrf5340_audio/`, the nRF5340 build script tries to build the CIS applications in the CIS unidirectional mode. +To switch to the bidirectional mode, see :ref:`nrf53_audio_app_configuration_select_bidirectional`. + +For other configuration options, see :ref:`nrf53_audio_app_configuration` and :ref:`nrf53_audio_app_fota`. + +For information about how to configure applications in the |NCS|, see :ref:`configure_application`. + +.. _nrf53_audio_unicast_server_app_building: + +Building and running +******************** + +This application can be found under :file:`applications/nrf5340_audio/unicast_server` in the nRF Connect SDK folder structure, but it uses :file:`.conf` files at :file:`applications/nrf5340_audio/`. + +The nRF5340 Audio DK comes preprogrammed with basic firmware that indicates if the kit is functional. +See :ref:`nrf53_audio_app_dk_testing_out_of_the_box` for more information. + +To build the application, see :ref:`nrf53_audio_app_building`. + +.. _nrf53_audio_unicast_server_app_testing: + +Testing +******* + +After building and programming the application, you can test the default CIS headset mode using one :ref:`unicast client application ` and one or two unicast server devices (this application). +The recommended approach is to use two other nRF5340 Audio DKs programmed with the :ref:`unicast client application ` for the CIS gateway and the unicast server application (this application) for the CIS headset, respectively, but you can also use an external device that supports the role of unicast server. + +.. note:: + |nrf5340_audio_external_devices_note| + +The following testing scenario assumes you are using USB as the audio source on the gateway. +This is the default setting. + +Complete the following steps to test the unidirectional CIS mode for one gateway and two headset devices: + +1. Make sure that the development kits are still plugged into the USB ports and are turned on. + + .. note:: + |usb_known_issues| + + **LED3** starts blinking green on every device to indicate the ongoing CPU activity on the application core. +#. Wait for the **LED1** on the gateway to start blinking blue. + This happens shortly after programming the development kit and indicates that the gateway device is connected to at least one headset and ready to send data. +#. Search the list of audio devices listed in the sound settings of your operating system for *nRF5340 USB Audio* (gateway) and select it as the output device. +#. Connect headphones to the **HEADPHONE** audio jack on both headset devices. +#. Start audio playback on your PC from any source. +#. Wait for **LED1** to blink blue on the headset. + When they do, the audio stream has started on the headset. + + .. note:: + The audio outputs only to the left channel of the audio jack, even if the given headset is configured as the right headset. + This is because of the mono hardware codec chip used on the development kits. + If you want to play stereo sound using one development kit, you must connect an external hardware codec chip that supports stereo. + +#. Wait for **LED2** to light up solid green on the headsets to indicate that the audio synchronization is achieved. +#. Press the **VOL+** button on one of the headsets. + The playback volume increases for the headset. +#. If you use more than one headset, hold down the **VOL+** button and press the **RESET** button on a headset. + After startup, this headset will be configured as the right channel headset. +#. If you use more than one headset, hold down the **VOL-** button and press the **RESET** button on a headset. + After startup, this headset will be configured as the left channel headset. + You can also just press the **RESET** button to restore the original programmed settings. + +For other testing options, refer to :ref:`nrf53_audio_unicast_server_app_ui`. + +After the kits have paired for the first time, they are now bonded. +This means the Long-Term Key (LTK) is stored on each side, and that the kits will only connect to each other unless the bonding information is cleared. +To clear the bonding information, press and hold **BTN 5** during boot or reprogram all the development kits. + +When you finish testing, power off the nRF5340 Audio development kits by switching the power switch from On to Off. + +.. _nrf53_audio_unicast_server_app_testing_steps_cis_walkie_talkie: + +Testing the walkie-talkie demo +============================== + +Testing the walkie-talkie demo is identical to the default testing procedure, except for the following differences: + +* You must enable the Kconfig option mentioned in :ref:`nrf53_audio_app_configuration_enable_walkie_talkie` before building the application. +* Instead of controlling the playback, you can speak through the PDM microphones. + The line is open all the time, no need to press any buttons to talk, but the volume control works as in the default testing procedure. + +Dependencies +************ + +For the list of dependencies, check the application's source files. diff --git a/applications/nrf5340_audio/unicast_server/main.c b/applications/nrf5340_audio/unicast_server/main.c new file mode 100644 index 00000000000..5a8e6a000ed --- /dev/null +++ b/applications/nrf5340_audio/unicast_server/main.c @@ -0,0 +1,539 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "streamctrl.h" + +#include + +#include "nrf5340_audio_common.h" +#include "nrf5340_audio_dk.h" +#include "led.h" +#include "button_assignments.h" +#include "macros_common.h" +#include "audio_system.h" +#include "button_handler.h" +#include "bt_le_audio_tx.h" +#include "bt_mgmt.h" +#include "bt_rendering_and_capture.h" +#include "audio_datapath.h" +#include "bt_content_ctrl.h" +#include "unicast_server.h" +#include "le_audio.h" +#include "le_audio_rx.h" + +#include +LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL); + +ZBUS_SUBSCRIBER_DEFINE(button_evt_sub, CONFIG_BUTTON_MSG_SUB_QUEUE_SIZE); + +ZBUS_MSG_SUBSCRIBER_DEFINE(le_audio_evt_sub); + +ZBUS_CHAN_DECLARE(button_chan); +ZBUS_CHAN_DECLARE(le_audio_chan); +ZBUS_CHAN_DECLARE(bt_mgmt_chan); +ZBUS_CHAN_DECLARE(volume_chan); + +ZBUS_OBS_DECLARE(volume_evt_sub); + +static struct k_thread button_msg_sub_thread_data; +static struct k_thread le_audio_msg_sub_thread_data; + +static k_tid_t button_msg_sub_thread_id; +static k_tid_t le_audio_msg_sub_thread_id; + +K_THREAD_STACK_DEFINE(button_msg_sub_thread_stack, CONFIG_BUTTON_MSG_SUB_STACK_SIZE); +K_THREAD_STACK_DEFINE(le_audio_msg_sub_thread_stack, CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE); + +static enum stream_state strm_state = STATE_PAUSED; + +/* Function for handling all stream state changes */ +static void stream_state_set(enum stream_state stream_state_new) +{ + strm_state = stream_state_new; +} + +/** + * @brief Handle button activity. + */ +static void button_msg_sub_thread(void) +{ + int ret; + const struct zbus_channel *chan; + + while (1) { + ret = zbus_sub_wait(&button_evt_sub, &chan, K_FOREVER); + ERR_CHK(ret); + + struct button_msg msg; + + ret = zbus_chan_read(chan, &msg, ZBUS_READ_TIMEOUT_MS); + ERR_CHK(ret); + + LOG_DBG("Got btn evt from queue - id = %d, action = %d", msg.button_pin, + msg.button_action); + + if (msg.button_action != BUTTON_PRESS) { + LOG_WRN("Unhandled button action"); + return; + } + + switch (msg.button_pin) { + case BUTTON_PLAY_PAUSE: + if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { + LOG_WRN("Play/pause not supported in walkie-talkie mode"); + break; + } + + if (bt_content_ctlr_media_state_playing()) { + ret = bt_content_ctrl_stop(NULL); + if (ret) { + LOG_WRN("Could not stop: %d", ret); + } + + } else if (!bt_content_ctlr_media_state_playing()) { + ret = bt_content_ctrl_start(NULL); + if (ret) { + LOG_WRN("Could not start: %d", ret); + } + + } else { + LOG_WRN("In invalid state: %d", strm_state); + } + + break; + + case BUTTON_VOLUME_UP: + ret = bt_r_and_c_volume_up(); + if (ret) { + LOG_WRN("Failed to increase volume: %d", ret); + } + + break; + + case BUTTON_VOLUME_DOWN: + ret = bt_r_and_c_volume_down(); + if (ret) { + LOG_WRN("Failed to decrease volume: %d", ret); + } + + break; + + case BUTTON_4: + if (IS_ENABLED(CONFIG_AUDIO_TEST_TONE)) { + if (IS_ENABLED(CONFIG_WALKIE_TALKIE_DEMO)) { + LOG_DBG("Test tone is disabled in walkie-talkie mode"); + break; + } + + if (strm_state != STATE_STREAMING) { + LOG_WRN("Not in streaming state"); + break; + } + + ret = audio_system_encode_test_tone_step(); + if (ret) { + LOG_WRN("Failed to play test tone, ret: %d", ret); + } + + break; + } + + break; + + case BUTTON_5: + if (IS_ENABLED(CONFIG_AUDIO_MUTE)) { + ret = bt_r_and_c_volume_mute(false); + if (ret) { + LOG_WRN("Failed to mute, ret: %d", ret); + } + + break; + } + + break; + + default: + LOG_WRN("Unexpected/unhandled button id: %d", msg.button_pin); + } + + STACK_USAGE_PRINT("button_msg_thread", &button_msg_sub_thread_data); + } +} + +/** + * @brief Handle Bluetooth LE audio events. + */ +static void le_audio_msg_sub_thread(void) +{ + int ret; + uint32_t pres_delay_us; + uint32_t bitrate_bps; + uint32_t sampling_rate_hz; + const struct zbus_channel *chan; + + while (1) { + struct le_audio_msg msg; + + ret = zbus_sub_wait_msg(&le_audio_evt_sub, &chan, &msg, K_FOREVER); + ERR_CHK(ret); + + LOG_DBG("Received event = %d, current state = %d", msg.event, strm_state); + + switch (msg.event) { + case LE_AUDIO_EVT_STREAMING: + LOG_DBG("LE audio evt streaming"); + + if (msg.dir == BT_AUDIO_DIR_SOURCE) { + audio_system_encoder_start(); + } + + if (strm_state == STATE_STREAMING) { + LOG_DBG("Got streaming event in streaming state"); + break; + } + + audio_system_start(); + stream_state_set(STATE_STREAMING); + ret = led_blink(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + case LE_AUDIO_EVT_NOT_STREAMING: + LOG_DBG("LE audio evt not streaming"); + + if (strm_state == STATE_PAUSED) { + LOG_DBG("Got not_streaming event in paused state"); + break; + } + + if (msg.dir == BT_AUDIO_DIR_SOURCE) { + audio_system_encoder_stop(); + } + + stream_state_set(STATE_PAUSED); + audio_system_stop(); + ret = led_on(LED_APP_1_BLUE); + ERR_CHK(ret); + + break; + + case LE_AUDIO_EVT_CONFIG_RECEIVED: + LOG_DBG("LE audio config received"); + + ret = unicast_server_config_get(msg.conn, msg.dir, &bitrate_bps, + &sampling_rate_hz, NULL); + if (ret) { + LOG_WRN("Failed to get config: %d", ret); + break; + } + + LOG_DBG("\tSampling rate: %d Hz", sampling_rate_hz); + LOG_DBG("\tBitrate (compressed): %d bps", bitrate_bps); + + if (msg.dir == BT_AUDIO_DIR_SINK) { + ret = audio_system_config_set(VALUE_NOT_SET, VALUE_NOT_SET, + sampling_rate_hz); + ERR_CHK(ret); + } else if (msg.dir == BT_AUDIO_DIR_SOURCE) { + ret = audio_system_config_set(sampling_rate_hz, bitrate_bps, + VALUE_NOT_SET); + ERR_CHK(ret); + } + + break; + + case LE_AUDIO_EVT_PRES_DELAY_SET: + LOG_DBG("Set presentation delay"); + + ret = unicast_server_config_get(msg.conn, BT_AUDIO_DIR_SINK, NULL, NULL, + &pres_delay_us); + if (ret) { + LOG_ERR("Failed to get config: %d", ret); + break; + } + + ret = audio_datapath_pres_delay_us_set(pres_delay_us); + if (ret) { + LOG_ERR("Failed to set presentation delay to %d", pres_delay_us); + break; + } + + LOG_INF("Presentation delay %d us is set by initiator", pres_delay_us); + + break; + + case LE_AUDIO_EVT_NO_VALID_CFG: + LOG_WRN("No valid configurations found, will disconnect"); + + ret = bt_mgmt_conn_disconnect(msg.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (ret) { + LOG_ERR("Failed to disconnect: %d", ret); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled le_audio event: %d", msg.event); + + break; + } + + STACK_USAGE_PRINT("le_audio_msg_thread", &le_audio_msg_sub_thread_data); + } +} + +/** + * @brief Create zbus subscriber threads. + * + * @return 0 for success, error otherwise. + */ +static int zbus_subscribers_create(void) +{ + int ret; + + button_msg_sub_thread_id = k_thread_create( + &button_msg_sub_thread_data, button_msg_sub_thread_stack, + CONFIG_BUTTON_MSG_SUB_STACK_SIZE, (k_thread_entry_t)button_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_BUTTON_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(button_msg_sub_thread_id, "BUTTON_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create button_msg thread"); + return ret; + } + + le_audio_msg_sub_thread_id = k_thread_create( + &le_audio_msg_sub_thread_data, le_audio_msg_sub_thread_stack, + CONFIG_LE_AUDIO_MSG_SUB_STACK_SIZE, (k_thread_entry_t)le_audio_msg_sub_thread, NULL, + NULL, NULL, K_PRIO_PREEMPT(CONFIG_LE_AUDIO_MSG_SUB_THREAD_PRIO), 0, K_NO_WAIT); + ret = k_thread_name_set(le_audio_msg_sub_thread_id, "LE_AUDIO_MSG_SUB"); + if (ret) { + LOG_ERR("Failed to create le_audio_msg thread"); + return ret; + } + + return 0; +} + +/** + * @brief Zbus listener to receive events from bt_mgmt. + * + * @param[in] chan Zbus channel. + * + * @note Will in most cases be called from BT_RX context, + * so there should not be too much processing done here. + */ +static void bt_mgmt_evt_handler(const struct zbus_channel *chan) +{ + int ret; + const struct bt_mgmt_msg *msg; + + msg = zbus_chan_const_msg(chan); + + switch (msg->event) { + case BT_MGMT_CONNECTED: + LOG_INF("Connected"); + + break; + + case BT_MGMT_DISCONNECTED: + LOG_INF("Disconnected"); + + ret = bt_content_ctrl_conn_disconnected(msg->conn); + if (ret) { + LOG_ERR("Failed to handle disconnection in content control: %d", ret); + } + + break; + + case BT_MGMT_SECURITY_CHANGED: + LOG_INF("Security changed"); + + ret = bt_r_and_c_discover(msg->conn); + if (ret) { + LOG_WRN("Failed to discover rendering services"); + } + + ret = bt_content_ctrl_discover(msg->conn); + if (ret == -EALREADY) { + LOG_DBG("Discovery in progress or already done"); + } else if (ret) { + LOG_ERR("Failed to start discovery of content control: %d", ret); + } + + break; + + default: + LOG_WRN("Unexpected/unhandled bt_mgmt event: %d", msg->event); + + break; + } +} + +ZBUS_LISTENER_DEFINE(bt_mgmt_evt_listen, bt_mgmt_evt_handler); + +/** + * @brief Link zbus producers and observers. + * + * @return 0 for success, error otherwise. + */ +static int zbus_link_producers_observers(void) +{ + int ret; + + if (!IS_ENABLED(CONFIG_ZBUS)) { + return -ENOTSUP; + } + + ret = zbus_chan_add_obs(&button_chan, &button_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add button sub"); + return ret; + } + + ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add le_audio sub"); + return ret; + } + + ret = zbus_chan_add_obs(&bt_mgmt_chan, &bt_mgmt_evt_listen, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add bt_mgmt sub"); + return ret; + } + + ret = zbus_chan_add_obs(&volume_chan, &volume_evt_sub, ZBUS_ADD_OBS_TIMEOUT_MS); + if (ret) { + LOG_ERR("Failed to add volume sub"); + return ret; + } + + return 0; +} + +static int ext_adv_populate(struct bt_data *ext_adv_buf, size_t ext_adv_buf_size, + size_t *ext_adv_count) +{ + int ret; + size_t ext_adv_buf_cnt = 0; + + NET_BUF_SIMPLE_DEFINE_STATIC(uuid_buf, CONFIG_EXT_ADV_UUID_BUF_MAX); + + ext_adv_buf[ext_adv_buf_cnt].type = BT_DATA_UUID16_SOME; + ext_adv_buf[ext_adv_buf_cnt].data_len = 0; + ext_adv_buf[ext_adv_buf_cnt].data = uuid_buf.data; + ext_adv_buf_cnt++; + + ret = bt_r_and_c_uuid_populate(&uuid_buf); + + if (ret) { + LOG_ERR("Failed to add adv data from renderer: %d", ret); + return ret; + } + + ret = bt_content_ctrl_uuid_populate(&uuid_buf); + + if (ret) { + LOG_ERR("Failed to add adv data from content ctrl: %d", ret); + return ret; + } + + ret = bt_mgmt_manufacturer_uuid_populate(&uuid_buf, CONFIG_BT_DEVICE_MANUFACTURER_ID); + if (ret) { + LOG_ERR("Failed to add adv data with manufacturer ID: %d", ret); + return ret; + } + + ret = unicast_server_adv_populate(&ext_adv_buf[ext_adv_buf_cnt], + ext_adv_buf_size - ext_adv_buf_cnt); + + if (ret < 0) { + LOG_ERR("Failed to add adv data from unicast server: %d", ret); + return ret; + } + + ext_adv_buf_cnt += ret; + + /* Add the number of UUIDs */ + ext_adv_buf[0].data_len = uuid_buf.len; + + LOG_DBG("Size of adv data: %d, num_elements: %d", sizeof(struct bt_data) * ext_adv_buf_cnt, + ext_adv_buf_cnt); + + *ext_adv_count = ext_adv_buf_cnt; + + return 0; +} + +uint8_t stream_state_get(void) +{ + return strm_state; +} + +void streamctrl_send(void const *const data, size_t size, uint8_t num_ch) +{ + int ret; + static int prev_ret; + + struct le_audio_encoded_audio enc_audio = {.data = data, .size = size, .num_ch = num_ch}; + + if (strm_state == STATE_STREAMING) { + ret = unicast_server_send(enc_audio); + + if (ret != 0 && ret != prev_ret) { + if (ret == -ECANCELED) { + LOG_WRN("Sending operation cancelled"); + } else { + LOG_WRN("Problem with sending LE audio data, ret: %d", ret); + } + } + + prev_ret = ret; + } +} + +int main(void) +{ + int ret; + static struct bt_data ext_adv_buf[CONFIG_EXT_ADV_BUF_MAX]; + + LOG_DBG("nRF5340 APP core started"); + + size_t ext_adv_buf_cnt = 0; + + ret = nrf5340_audio_dk_init(); + ERR_CHK(ret); + + ret = nrf5340_audio_common_init(); + ERR_CHK(ret); + + ret = zbus_subscribers_create(); + ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads"); + + ret = zbus_link_producers_observers(); + ERR_CHK_MSG(ret, "Failed to link zbus producers and observers"); + + ret = le_audio_rx_init(); + ERR_CHK_MSG(ret, "Failed to initialize rx path"); + + ret = unicast_server_enable(le_audio_rx_data_handler); + ERR_CHK_MSG(ret, "Failed to enable LE Audio"); + + ret = bt_r_and_c_init(); + ERR_CHK(ret); + + ret = bt_content_ctrl_init(); + ERR_CHK(ret); + + ret = ext_adv_populate(ext_adv_buf, ARRAY_SIZE(ext_adv_buf), &ext_adv_buf_cnt); + ERR_CHK(ret); + + ret = bt_mgmt_adv_start(ext_adv_buf, ext_adv_buf_cnt, NULL, 0, true); + ERR_CHK(ret); + + return 0; +} diff --git a/applications/nrf_desktop/README.rst b/applications/nrf_desktop/README.rst index b566b4d5821..ef77a61edd6 100644 --- a/applications/nrf_desktop/README.rst +++ b/applications/nrf_desktop/README.rst @@ -3,2386 +3,28 @@ nRF Desktop ########### -.. contents:: - :local: - :depth: 2 - -The nRF Desktop is a reference design of a Human Interface Device (HID) that is connected to a host through Bluetooth® Low Energy or USB, or both. -Depending on the configuration, this application can work as desktop mouse, gaming mouse, keyboard, or connection dongle. -See `nRF Desktop reference design page`_ for an overview of supported features. - -.. tip:: - To get started with hardware that has pre-configured software, go to the `User interface`_ section. - -The nRF Desktop application supports common input hardware interfaces like motion sensors, rotation sensors, and buttons scanning module. -You can configure the firmware at runtime using a dedicated configuration channel established with the HID feature report. -The same channel is used to transmit DFU packets. - -.. _nrf_desktop_architecture: - -Overview: Firmware architecture -******************************* - -The nRF Desktop application design aims at high performance, while still providing configurability and extensibility. - -The application architecture is modular, event-driven and build around :ref:`lib_caf`. -This means that parts of the application functionality are separated into isolated modules that communicate with each other using application events, which are handled by the :ref:`app_event_manager`. -Modules register themselves as listeners of those events that they are configured to react to. -An application event can be submitted by multiple modules and it can have multiple listeners. - -Module and component overview -============================= - -The following figure shows the nRF Desktop modules and how they relate with other components and the :ref:`app_event_manager`. -The figure does not present all the available modules. -For example, the figure does not include the modules that are used as hotfixes or only for debug or profiling purposes. - -.. figure:: /images/nrf_desktop_arch.svg - :alt: nRF Desktop high-level design (overview) - - Application high-level design overview - -For more information about each of nRF Desktop modules, see the :ref:`nrf_desktop_app_internal_modules` section. - -Module event tables -------------------- - -The :ref:`documentation page of each application module ` includes a table that shows the event-based communication for the module. - -+---------------------------------------+-------------+------------------------------------+--------------+-----------------------------------------+ -| Source Module | Input Event | This Module | Output Event | Sink Module | -+=======================================+=============+====================================+==============+=========================================+ -| The module that submits ``eventA``. | ``eventA`` | The module described by the table. | | | -+---------------------------------------+ | | | | -| Other module that submits ``eventA``. | | | | | -+---------------------------------------+-------------+ +--------------+-----------------------------------------+ -| The module that submits ``eventB``. | ``eventB`` | | | | -+---------------------------------------+-------------+ +--------------+-----------------------------------------+ -| | | | ``eventC`` | The module that reacts on ``eventC``. | -+---------------------------------------+-------------+------------------------------------+--------------+-----------------------------------------+ - -Each module event table contains the following columns: - -Source Module - The module that submits a given application event. - Some of these events can have many listeners or sources. - These are listed on the :ref:`nrf_desktop_event_rel_modules` page. - -Input Event - An application event that is received by the module described by the table. - -This Module - The module described by the table. - This is the module that is the target of the Input Events and the source of Output Events directed to the Sink Modules. - -Output Event - An application event that is submitted by the module described by the table. - -Sink Module - The module that reacts on the application event. - Some of these events can have many listeners or sources. - These are listed on the :ref:`nrf_desktop_event_rel_modules` page. - -.. note:: - Some application modules can have multiple implementations (for example, :ref:`nrf_desktop_motion`). - In such case, the table shows the :ref:`app_event_manager` events received and submitted by all implementations of a given application module. - -Module usage per hardware type -============================== - -Since the application architecture is uniform and the code is shared, the set of modules in use depends on the selected device role. -A different set of modules is enabled when the application is working as mouse, keyboard, or dongle. -In other words, not all of the :ref:`nrf_desktop_app_internal_modules` need to be enabled for a given reference design. - -Gaming mouse module set ------------------------ - -The following figure shows the modules that are enabled when the application is working as a gaming mouse: - -.. figure:: /images/nrf_desktop_arch_gmouse.svg - :alt: nRF Desktop high-level design (gaming mouse) - - Application configured as a gaming mouse - -Desktop mouse module set ------------------------- - -The following figure shows the modules that are enabled when the application is working as a desktop mouse: - -.. figure:: /images/nrf_desktop_arch_dmouse.svg - :alt: nRF Desktop high-level design (desktop mouse) - - Application configured as a desktop mouse - -Keyboard module set -------------------- - -The following figure shows the modules that are enabled when the application is working as a keyboard: - -.. figure:: /images/nrf_desktop_arch_kbd.svg - :alt: nRF Desktop high-level design (keyboard) - - Application configured as a keyboard - -Dongle module set ------------------ - -The following figure shows the modules that are enabled when the application is working as a dongle: - -.. figure:: /images/nrf_desktop_arch_dongle.svg - :alt: nRF Desktop high-level design (dongle) - - Application configured as a dongle - -Thread usage -============ - -The application limits the number of threads in use to the minimum and does not use the user-space threads. - -The following threads are kept running in the application: - -* System-related threads - * Idle thread - * System workqueue thread - * Logger thread (when :ref:`zephyr:logging_api` is enabled) - * Shell thread (when :ref:`zephyr:shell_api` is enabled) - * Threads related to Bluetooth® LE (the exact number depends on the selected Link Layer) -* Application-related threads - * Motion sensor thread (running only on mouse) - * Settings loading thread (enabled by default only on keyboard) - * QoS data sampling thread (running only if Bluetooth® LE QoS feature is enabled) - -Most of the application activity takes place in the context of the system work queue thread, either through scheduled work objects or through the Application Event Manager callbacks (executed from the system workqueue thread). -Because of this, the application does not need to handle resource protection. -The only exception are places where the interaction with interrupts or multiple threads cannot be avoided. - -Memory allocation -================= - -Most of memory resources that are used by the application are allocated statically. - -The application uses dynamic allocation to: - -* Create the Application Event Manager events. - For more information, see the :ref:`app_event_manager` page. -* Temporarily store the HID-related data in the :ref:`nrf_desktop_hid_state` and :ref:`nrf_desktop_hid_forward`. - For more information, see the documentation pages of these modules. - -When configuring HEAP, make sure that the values for the following options match the typical event size and the system needs: - -* :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE` - The size must be big enough to handle the worst possible use case for the given device. - -.. important:: - The nRF Desktop uses ``k_heap`` as the backend for dynamic allocation. - This backend is used by default in Zephyr. - For more information, refer to Zephyr's documentation about :ref:`zephyr:heap_v2`. - -HID data handling -================= - -The nRF Desktop device and the host can exchange HID data using one of the following HID report types: - -* HID input report -* HID output report -* HID feature report - -The nRF Desktop application uses all of these report types. -See sections below for details about handling given HID report type. - -HID input reports ------------------ - -The nRF Desktop application uses HID input reports to transmit information about user input from the nRF Desktop device to a host. -The user input can be, for example, button press or mouse motion. - -The nRF Desktop supports the following HID input reports: - -* HID mouse report -* HID keyboard report -* HID consumer control report -* HID system control report - -Every of these reports uses predefined report format and provides the given information. -For example, the mouse motion is forwarded as HID mouse report. - -An nRF Desktop device supports the selected subset of the HID input reports. -For example, the nRF Desktop keyboard reference design (nrf52kbd_nrf52832) supports HID keyboard report, HID consumer control report and HID system control report. - -As an example, the following section describes handling HID mouse report data. - -HID mouse report handling -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The nRF Desktop mouse sends HID input reports to the host after the host connects and subscribes for the HID reports. - -The :ref:`nrf_desktop_motion` sensor sampling is synchronized with sending the HID mouse input reports to the host. - -The :ref:`nrf_desktop_wheel` and :ref:`caf_buttons` provide data to the :ref:`nrf_desktop_hid_state` when the mouse wheel is used or a button is pressed, respectively. -These inputs are not synchronized with the HID report transmission to the host. - -When the mouse is constantly in use, the motion module is kept in the fetching state. -In this state, the nRF Desktop mouse forwards the data from the motion sensor to the host in the following way: - -1. USB state (or Bluetooth HIDS) sends a HID mouse report to the host and submits ``hid_report_sent_event``. -#. The event triggers sampling of the motion sensor. -#. A dedicated thread is used to fetch the sample from the sensor. -#. After the sample is fetched, the thread forwards it to the :ref:`nrf_desktop_hid_state` as ``motion_event``. -#. The |hid_state| updates the HID report data, generates new HID input report, and submits it as ``hid_report_event``. -#. The HID report data is forwarded to the host either by the :ref:`nrf_desktop_usb_state` or by the :ref:`nrf_desktop_hids`. - The USB state has precedence if the USB is connected. -#. When the HID input report is sent to the host, ``hid_report_sent_event`` is submitted. - The motion sensor sample is triggered and the sequence repeats. - -If the device is connected through Bluetooth, the :ref:`nrf_desktop_hid_state` uses a pipeline that consists of two HID reports, which it creates upon receiving the first ``motion_event``. -The |hid_state| submits two ``hid_report_event`` events. -Sending the first event to the host triggers the motion sensor sample. - -For the Bluetooth connections, submitting ``hid_report_sent_event`` is delayed by one Bluetooth connection interval. -Because of this delay, the :ref:`nrf_desktop_hids` requires pipeline of two HID reports to make sure that data is sent on every connection event. -Such solution is necessary to achieve high report rate. - -If there is no motion data for the predefined number of samples, the :ref:`nrf_desktop_motion` goes to the idle state. -This is done to reduce the power consumption. -When a motion is detected, the module switches back to the fetching state. - -The following diagram shows the data exchange between the application modules. -To keep it simple, the diagram only shows data related to HID input reports that are sent after the host is connected and the HID subscriptions are enabled. - -.. figure:: /images/nrf_desktop_motion_sensing.svg - :alt: nRF Desktop mouse HID data sensing and transmission - - nRF Desktop mouse HID data sensing and transmission - -HID output reports ------------------- - -HID output reports are used to transmit data from host to an nRF Desktop device. -The nRF Desktop supports the HID keyboard LED report. -The report is used by the host to update the state of the keyboard LEDs, for example to indicate that the Caps Lock key is active. - -.. note:: - Only the nrf52840dk_nrf52840 in ``keyboard`` configuration has hardware LEDs that can be used to display the Caps Lock and Num Lock state. - -The following diagrams show the HID output report data exchange between the application modules. - -* Scenario 1: Peripheral connected directly to the host - - .. figure:: /images/nrf_desktop_peripheral_host.svg - :alt: HID output report: Data handling and transmission between host and peripheral - - HID output report: Data handling and transmission between host and peripheral - - In this scenario, the HID output report is sent from the host to the peripheral either through Bluetooth or the USB connection. - Depending on the connection, the HID report is received by the :ref:`nrf_desktop_hids` or :ref:`nrf_desktop_usb_state`, respectively. - The module then sends the HID output report as ``hid_report_event`` to the :ref:`nrf_desktop_hid_state`, which keeps track of the HID output report states and updates state of the hardware LEDs by sending ``led_event`` to :ref:`nrf_desktop_leds`. - -* Scenario 2: Dongle intermediates between the host and the peripheral - - .. figure:: /images/nrf_desktop_peripheral_host_dongle.svg - :alt: HID output report: Data handling and transmission between host and peripheral through dongle - - HID output report: Data handling and transmission between host and peripheral through dongle - - In this scenario, the HID output report is sent from the host to the dongle using the USB connection and is received by the :ref:`nrf_desktop_usb_state`. - The destination module then sends the HID output report as ``hid_report_event`` to the :ref:`nrf_desktop_hid_forward`, which sends it to the peripheral using Bluetooth. - -HID feature reports -------------------- - -HID feature reports are used to transmit data between the host and an nRF Desktop device (in both directions). -The nRF Desktop uses only one HID feature report: the user config report. -The report is used by the :ref:`nrf_desktop_config_channel`. - -.. note:: - The nRF Desktop also uses a dedicated HID output report to forward the :ref:`nrf_desktop_config_channel` data through the nRF Desktop dongle. - This report is handled using the configuration channel's infrastructure and it can be enabled using :ref:`CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT `. - See the Kconfig option's help for details about the report. - -HID protocols -------------- - -The following HID protocols are supported by nRF Desktop for HID input reports and HID output reports: - -* Report protocol - Most widely used in HID devices. - When establishing connection, host reads a HID descriptor from the HID device. - HID descriptor describes format of HID reports and is used by the host to interpret data exchanged between HID device and host. -* Boot protocol - Only available for mice and keyboards data. - No HID descriptor is used for this HID protocol. - Instead, fixed data packet formats must be used to send data between the HID device and the host. - -Requirements -************ - -The nRF Desktop application supports several development kits related to the following hardware reference designs. -Depending on what development kit you use, you need to select the respective configuration file and :ref:`build type `. - -.. tabs:: - - .. tab:: Gaming mouse - - .. figure:: /images/nrf_desktop_gaming_mouse_top_no_captions.svg - :alt: nRF Desktop gaming mouse (top view) - - .. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf52840gmouse_nrf52840 - - .. tab:: Desktop mouse - - .. figure:: /images/nrf_desktop_desktop_mouse_side_no_captions.svg - :alt: nRF Desktop desktop mouse (side view) - - .. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf52dmouse_nrf52832, nrf52810dmouse_nrf52810 - - .. tab:: Keyboard - - .. figure:: /images/nrf_desktop_keyboard_top_no_captions.svg - :alt: nRF Desktop keyboard (top view) - - .. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf52kbd_nrf52832 - - .. tab:: HID dongle - - .. figure:: /images/nrf_desktop_dongle_no_captions.svg - :alt: nRF Desktop dongle (top view) - - .. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf52840dongle_nrf52840, nrf52833dongle_nrf52833, nrf52820dongle_nrf52820 - - .. tab:: DK - - .. figure:: /images/nrf_desktop_nrf52840_dk_no_captions.svg - :alt: DK - - .. table-from-rows:: /includes/sample_board_rows.txt - :header: heading - :rows: nrf52840dk_nrf52840, nrf52833dk_nrf52833, nrf52833dk_nrf52820, nrf5340dk_nrf5340_cpuapp - - Depending on the configuration, a DK may act either as mouse, keyboard or dongle. - You can check supported configurations for each board in the :ref:`nrf_desktop_board_configuration_files` section. - -.. - -The application is designed to allow easy porting to new hardware. -Check :ref:`nrf_desktop_porting_guide` for details. - -.. _nrf_desktop_requirements_build_types: - -nRF Desktop build types -======================= - -The nRF Desktop application does not use a single :file:`prj.conf` file. -Before you start testing the application, you can select one of the build types supported by the application, depending on your development kit and the building method. -Not every board supports all of the mentioned build types. - -See :ref:`app_build_additions_build_types` and :ref:`modifying_build_types` for more information about this feature of the |NCS|. - -The application supports the following build types: - -.. list-table:: nRF Desktop build types - :widths: auto - :header-rows: 1 - - * - Build type - - File name - - Supported board - - Description - * - Debug - - :file:`prj.conf` - - All from `Requirements`_ - - | Debug version of the application; the same as the release build type, but with debug options enabled. - | Used by default if no build type is explicitly selected. - * - Release - - :file:`prj_release.conf` - - All from `Requirements`_ - - Release version of the application with no debugging features. - * - Debug Fast Pair - - :file:`prj_fast_pair.conf` - - ``nrf52840dk_nrf52840``, ``nrf52840gmouse_nrf52840`` - - Debug version of the application with `Fast Pair`_ support. - * - Release Fast Pair - - :file:`prj_release_fast_pair.conf` - - ``nrf52kbd_nrf52832``, ``nrf52840gmouse_nrf52840`` - - Release version of the application with `Fast Pair`_ support. - * - Dongle - - :file:`prj_dongle.conf` - - ``nrf52840dk_nrf52840`` - - Debug version of the application that lets you generate the application with the dongle role. - * - Keyboard - - :file:`prj_keyboard.conf` - - ``nrf52840dk_nrf52840`` - - Debug version of the application that lets you generate the application with the keyboard role. - * - MCUboot QSPI - - :file:`prj_mcuboot_qspi.conf` - - ``nrf52840dk_nrf52840`` - - Debug version of the application that uses MCUboot with the secondary slot in the external QSPI FLASH. - * - MCUboot SMP - - :file:`prj_mcuboot_smp.conf` - - ``nrf52840dk_nrf52840``, ``nrf52840gmouse_nrf52840`` - - | Debug version of the application that enables MCUmgr with DFU support and offers support for the MCUboot DFU procedure over SMP. - | See the :ref:`nrf_desktop_bootloader_background_dfu` section for more information. - * - WWCB - - :file:`prj_wwcb.conf` - - ``nrf52840dk_nrf52840`` - - Debug version of the application with the support for the B0 bootloader enabled for `Works With ChromeBook (WWCB)`_. - * - Triple Bluetooth® LE connection - - :file:`prj_3bleconn.conf` - - ``nrf52840dongle_nrf52840`` - - Debug version of the application with the support for up to three simultaneous Bluetooth® LE connections. - * - Quadruple LLPM connection - - :file:`prj_4llpmconn.conf` - - ``nrf52840dongle_nrf52840`` - - Debug version of the application with the support for up to four simultaneous Bluetooth® LE connections, in Low Latency Packet Mode. - * - Release quadruple LLPM connection - - :file:`prj_release_4llpmconn.conf` - - ``nrf52840dongle_nrf52840`` - - Release version of the application with the support for up to four simultaneous Bluetooth® LE connections, in Low Latency Packet Mode. - -.. note:: - Bootloader-enabled configurations with support for :ref:`serial recovery DFU ` or :ref:`background DFU ` are set as default if they fit in non-volatile memory. - See :ref:`nrf_desktop_board_configuration_files` for details about which boards have bootloader included in their default configuration. - -See :ref:`nrf_desktop_porting_guide` for detailed information about the application configuration and how to create build type files for your hardware. - -User interface -************** - -The nRF Desktop configuration files have a set of preprogrammed options bound to different parts of the hardware. -These options are related to the functionalities discussed in this section. - -Turning devices on and off -========================== - -The nRF Desktop hardware reference designs are equipped with hardware switches to turn the device on and off. -See the following figures for the exact location of these switches: - -.. tabs:: - - .. tab:: Gaming mouse - - .. figure:: /images/nrf_desktop_gaming_mouse_bottom.svg - :alt: nRF Desktop gaming mouse (bottom view) - - The switch is located at the bottom of the gaming mouse, close to the optical sensor. - The mouse uses this switch also for changing dongle and Bluetooth LE peers, as described in the `Bluetooth LE peer control`_ section. - - .. tab:: Desktop mouse - - .. figure:: /images/nrf_desktop_desktop_mouse_bottom.svg - :alt: nRF Desktop desktop mouse (bottom view) - - The switch is located at the bottom of the desktop mouse, close to the optical sensor. - - .. tab:: Keyboard - - .. figure:: /images/nrf_desktop_keyboard_back_power.svg - :alt: nRF Desktop keyboard (back view) - - The switch is located at the back of the keyboard. - -.. - -Connectability -============== - -The nRF Desktop devices provide user input to the host in the same way as other mice and keyboards, using connection through USB or Bluetooth LE. - -The nRF Desktop devices support additional operations, like firmware upgrade or configuration change. -The support is implemented through the :ref:`nrf_desktop_config_channel`. -The host can use dedicated Python scripts to exchange the data with an nRF Desktop peripheral. -For detailed information, see :ref:`nrf_desktop_config_channel_script`. - -To save power, the behavior of a device can change in time. -For more information, see the `Power management`_ section. - -.. _nrf_desktop_usb: - -Connection through USB ----------------------- - -The nRF Desktop devices use the USB HID class. -No additional software or drivers are required. - -.. tabs:: - - .. tab:: Gaming mouse - - .. figure:: /images/nrf_desktop_gaming_mouse_usb_slot.svg - :alt: nRF Desktop gaming mouse (top view) - - The gaming mouse has the USB connector slot located below the scroll wheel. - The connector should slide in the socket along the cut in the mouse base. - - .. tab:: HID dongle - - .. figure:: /images/nrf_desktop_dongle_usb.svg - :alt: nRF Desktop dongle - - The dongle has a USB connector located at one end of the board. - It should be inserted to the USB slot located on the host. - -.. - -Gaming mouse, dongle, and DK support the HID data transmission through USB. - -Gaming mouse USB -~~~~~~~~~~~~~~~~ - -The gaming mouse can send HID data when connected through USB. -When the device is connected both wirelessly and through USB at the same time, it provides input only through the USB connection. -If the device is disconnected from USB, it automatically switches to sending the data wirelessly using Bluetooth LE. - -The gaming mouse is a battery-powered device. -When it is connected through USB, charging of the rechargeable batteries starts. - -Dongle USB -~~~~~~~~~~ - -The nRF Desktop dongle works as a bridge between the devices connected through standard Bluetooth® Low Energy or Low Latency Packet Mode and the host connected through USB. -It receives data wirelessly from the connected peripherals and forwards the data to the host. - -The nRF Desktop dongle is powered directly through USB. - -DK USB -~~~~~~ - -The DK functionality depends on the application configuration. -Depending on the selected configuration options, it can work as a mouse, keyboard, or a dongle. - -.. _nrf_desktop_ble: - -Connection through Bluetooth LE -------------------------------- - -When turned on, the nRF Desktop peripherals are advertising until they go to the suspended state or connect through Bluetooth. -The peripheral supports one wireless connection at a time, but it can be bonded with :ref:`multiple peers `. - -.. note:: - To simplify pairing the nRF Desktop peripherals with Windows 10 hosts, the peripherals include `Swift Pair`_ payload in the Bluetooth LE advertising data. - By default, the Swift Pair payload is included for all of the Bluetooth local identities, apart from the dedicated local identity used for connection with an nRF Desktop dongle. - - Some of the nRF Desktop configurations also include `Fast Pair`_ payload in the Bluetooth LE advertising data to simplify pairing the nRF Desktop peripherals with Android hosts. - These configurations apply further modifications that are needed to improve the user experience. - See the :ref:`nrf_desktop_bluetooth_guide_fast_pair` documentation section for details. - -The nRF Desktop Bluetooth Central device scans for all bonded peripherals that are not connected. -Right after entering the scanning state, the scanning operation is uninterruptable for a predefined time (:kconfig:option:`CONFIG_DESKTOP_BLE_FORCED_SCAN_DURATION_S`) to speed up connection establishment with Bluetooth Peripherals. -After the timeout, the scanning is interrupted when any device connected to the dongle through Bluetooth comes in use. -A connected peripheral is considered in use when it provides HID input reports. -Continuing the scanning in such scenario would cause report rate drop. - -The scanning starts automatically when one of the bonded peers disconnects. -It also takes place periodically when a known peer is not connected. - -The peripheral connection can be based on standard Bluetooth LE connection parameters or on Bluetooth LE with Low Latency Packet Mode (LLPM). - -LLPM is a proprietary Bluetooth extension from Nordic Semiconductor. -It can be used only if it is supported by both connected devices (desktop mice do not support it). -LLPM enables sending data with high report rate (up to 1000 reports per second), which is not supported by the standard Bluetooth LE. - -.. _nrf_desktop_ble_peers: - -Bluetooth LE peer control -~~~~~~~~~~~~~~~~~~~~~~~~~ - -A connected Bluetooth LE peer device can be controlled using predefined buttons or button combinations. -There are several peer operations available. - -The application distinguishes between the following button press types: - -* Short - Button pressed for less than 0.5 seconds. -* Standard - Button pressed for more than 0.5 seconds, but less than 5 seconds. -* Long - Button pressed for more than 5 seconds. -* Double - Button pressed twice in quick succession. - -The peer operation states provide visual feedback through LEDs (if the device has LEDs). -Each of the states is represented by separate LED color and effect. -The LED colors and effects are described in the :file:`led_state_def.h` file located in the board-specific directory in the application configuration directory. - -The assignments of hardware interface elements depend on the device type. - -.. tabs:: - - .. tab:: Gaming mouse - - The following predefined hardware interface elements are assigned to peer control operations for the gaming mouse: - - Hardware switch - * The switch is located next to the optical sensor. - - .. figure:: /images/nrf_desktop_gaming_mouse_bottom.svg - :alt: nRF Desktop gaming mouse - bottom view - - nRF Desktop gaming mouse - bottom view - - * You can set the switch in the following positions: - - * Top position: Select the dongle peer. - * Middle position: Select the Bluetooth LE peers. - * Bottom position: Mouse turned off. - - When the dongle peer is selected, the peer control is disabled until the switch is set to another position. - - Peer control button - * The button is located on the left side of the mouse, in the thumb area. - - .. figure:: /images/nrf_desktop_gaming_mouse_led1_peer_control_button.svg - :alt: nRF Desktop gaming mouse - side view - - nRF Desktop gaming mouse - side view - - * Short-press to initialize the peer selection. - (The **LED1** changes color and starts blinking.) - During the peer selection: - - 1. Short-press to toggle between available peers. - The **LED1** changes color for each peer and keeps blinking. - #. Double-press to confirm the peer selection. - The peer is changed after the confirmation. - **LED1** stops blinking. - - .. note:: - |led_note| - - * Long-press to initialize the peer erase. - When **LED1** starts blinking rapidly, double-press to confirm the operation. - |nRF_Desktop_confirmation_effect| - * |nRF_Desktop_cancel_operation| - - .. tab:: Desktop mouse - - The following predefined buttons are assigned to peer control operations for the desktop mouse: - - Scroll wheel button - * Press the scroll wheel before the mouse is powered up with the on/off switch. - Long-press to initialize and confirm the peer erase. - - .. figure:: /images/nrf_desktop_desktop_mouse_side_scroll.svg - :alt: nRF Desktop desktop mouse - side view - - nRF Desktop desktop mouse - side view - - |nRF_Desktop_confirmation_effect| - * |nRF_Desktop_cancel_operation| - - .. tab:: Keyboard - - The following predefined buttons or button combinations are assigned to peer control operations for the keyboard: - - Page Down key - * Press the Page Down key while keeping the Fn modifier key pressed. - - .. figure:: /images/nrf_desktop_keyboard_top.svg - :alt: nRF Desktop keyboard - top view - - nRF Desktop keyboard - top view - - * Short-press the Page Down key to initialize the peer selection. - During the peer selection: - - 1. Short-press to toggle between available peers. - **LED1** blinks rapidly for each peer. - The amount of blinks corresponds to the number assigned to a peer: one blink for peer 1, two blinks for peer 2, and so on. - #. Double-press to confirm the peer selection. - The peer is changed after the confirmation. - **LED1** becomes solid for a short time and then turns itself off. - - .. note:: - |led_note| - - * Long-press to initialize the peer erase. - When **LED1** starts blinking rapidly, double-press to confirm the operation. - |nRF_Desktop_confirmation_effect| - * |nRF_Desktop_cancel_operation| - - .. tab:: HID dongle - - The following predefined buttons are assigned to peer control operations for the HID dongle: - - SW1 button - * The **SW1** button is located on the top of the dongle, on the same side as **LED2**. - - .. figure:: /images/nrf_desktop_dongle_front_led2_sw1.svg - :alt: nRF Desktop dongle - top view - - nRF Desktop dongle - top view - - * Long-press to initialize peer erase. - When **LED2** starts blinking rapidly, double-press to confirm the operation. - After the confirmation, all the Bluetooth bonds are removed for the dongle. - * Short-press to start scanning for both bonded and non-bonded Bluetooth Peripherals. - After the forced scan timeout, the scan is interrupted if another peripheral connected to the dongle is in use. - - .. note:: - |led_note| - - * |nRF_Desktop_cancel_operation| - -.. - -System state indication -======================= - -When available, one of the LEDs is used to indicate the state of the device. -This system state LED is kept on when the device is active. - -.. tabs:: - - .. tab:: Gaming mouse - - .. figure:: /images/nrf_desktop_gaming_mouse_led2.svg - :alt: nRF Desktop gaming mouse (top view) - - The system state LED of the gaming mouse is located under the transparent section of the cover. - The color of the LED changes when the device's battery is being charged. - - .. tab:: HID dongle - - .. figure:: /images/nrf_desktop_dongle_front_led1.svg - :alt: nRF Desktop dongle - - **LED1** is used for the system state indication. - It is located in the bottom right corner of the dongle, next to the USB connector. - -.. - -In case of a system error, the system state LED will start to blink rapidly for some time before the device is reset. - -.. _nrf_desktop_debugging: - -Debugging -========= - -Each of the nRF Desktop hardware reference designs has a slot for the dedicated debug board. -See the following figures for the exact location of these slots. - -.. tabs:: - - .. tab:: Gaming mouse - - .. figure:: /images/nrf_desktop_gaming_mouse_debug_board_slot.svg - :alt: nRF Desktop gaming mouse (top view) - - The debug slot is located at the end of the gaming mouse, below the cover. - - .. tab:: Desktop mouse - - .. figure:: /images/nrf_desktop_desktop_mouse_side_debug.svg - :alt: nRF Desktop desktop mouse (side view) - - The debug slot is located on the side of the desktop mouse. - It is accesible through a hole in the casing. - - .. tab:: Keyboard - - .. figure:: /images/nrf_desktop_keyboard_back_debug.svg - :alt: nRF Desktop keyboard (back view) - - The debug slot is located on the back of the keyboard. - -.. - -The boards that you can plug into these slots are shown below. -The debug board can be used for programming the device (and powering it). -The bypass boards are needed to make the device work when the debug board is not used. -Their purpose is to close the circuits, which allows the device to be powered, for example during :ref:`nrf_desktop_testing_steps`. - -.. tabs:: - - .. tab:: Debug board - - .. figure:: /images/nrf_desktop_400391_jlink_debug.svg - :alt: nRF Desktop debug board - - The device can be programmed using the J-Link. - The J-Link connector slot is located on the top of the debug board. - - .. tab:: Short bypass board - - .. figure:: /images/nrf_desktop_400398_debug.svg - :alt: nRF Desktop bypass board (short) - - The shorter nRF desktop bypass board can be used with the desktop mouse. - - .. tab:: Long bypass board - - .. figure:: /images/nrf_desktop_400398_long_debug.svg - :alt: nRF Desktop bypass board (long) - - The longer nRF desktop bypass board can be used with the gaming mouse. - -.. - -Power management -================ - -Reducing power consumption is important for every battery-powered device. - -The nRF Desktop peripherals are either suspended or powered off when they are not in use for a defined amount of time: - -* In the suspended state, the device maintains the active connection. -* In the powered off state, the CPU is switched to the off mode. - -In both cases, most of the functionalities are disabled. -For example, LEDs are turned off and advertising is stopped. - -Moving the mouse or pressing any button wakes up the device and turns on the disabled functionalities. - -You can define the amount of time after which the peripherals are suspended or powered off in :kconfig:option:`CONFIG_CAF_POWER_MANAGER_TIMEOUT`. -By default, this period is set to 120 seconds. - -.. important:: - When the gaming mouse is powered from USB, the power down timeout functionality is disabled. - - If a nRF Desktop device supports remote wakeup, the USB connected device goes to suspended state when USB is suspended. - The device can then trigger remote wakeup of the connected host on user input. - -Configuration -************* - -|config| - -Adding nRF21540 EK shield support -================================= - -The nRF Desktop application can be used with the :ref:`ug_radio_fem_nrf21540ek` shield, an RF front-end module (FEM) for the 2.4 GHz range extension. -The shield can be used with any nRF Desktop HID application configured for a development kit that is fitted with Arduino-compatible connector (see the :guilabel:`DK` tab in `Requirements`_). -This means that the shield support is not available for nRF Desktop's dedicated boards, such as ``nrf52840gmouse_nrf52840``, ``nrf52kbd_nrf52832``, or ``nrf52840dongle_nrf52840``. - -Low Latency Packet mode ------------------------ - -The RF front-end module (FEM) cannot be used together with Low Latency Packet Mode (LLPM) due to timing requirements. -The LLPM support in the nRF Desktop application (:kconfig:option:`CONFIG_CAF_BLE_USE_LLPM`) must be disabled for builds with FEM. - -Building with EK shield support -------------------------------- - -To build the application with the shield support, pass the ``SHIELD`` parameter to the build command. -Make sure to also disable the LLPM support. -For example, you can build the application for ``nrf52840dk_nrf52840`` with ``nrf21540ek`` shield using the following command: - -.. code-block:: console - - west build -b nrf52840dk_nrf52840 -- -DSHIELD=nrf21540ek -DCONFIG_CAF_BLE_USE_LLPM=n - -For the multi-core build, you need to pass the ``SHIELD`` parameter to images built on both application and network core. -The network core controls the FEM, but the application core needs to forward the needed pins to the network core. -Use ``hci_ipc_`` as the *childImageName* parameter, because in the nRF Desktop application, network core runs using ``hci_ipc_``. -The command for ``nrf5340dk_nrf5340_cpuapp`` with ``nrf21540ek`` shield would look as follows: - -.. code-block:: console - - west build -b nrf5340dk_nrf5340_cpuapp -- -DSHIELD=nrf21540ek_fwd -Dhci_ipc_SHIELD=nrf21540ek -DCONFIG_CAF_BLE_USE_LLPM=n - -For detailed information about building an application using the nRF21540 EK, see the :ref:`ug_radio_fem_nrf21540ek_programming` section in the Working with RF Front-end modules documentation. - -Building and running -******************** - -.. |sample path| replace:: :file:`applications/nrf_desktop` - -The nRF Desktop application is built the same way to any other |NCS| application or sample. - -.. include:: /includes/build_and_run.txt - -.. note:: - Information about the known issues in nRF Desktop can be found in |NCS|'s :ref:`release_notes` and on the :ref:`known_issues` page. - -.. _nrf_desktop_selecting_build_types: - -Selecting a build type -====================== - -Before you start testing the application, you can select one of the :ref:`nrf_desktop_requirements_build_types`, depending on your development kit and building method. -See :ref:`modifying_build_types` for detailed steps how to select a build type. - -.. note:: - If nRF Desktop is built with `Fast Pair`_ support, you must provide Fast Pair Model ID and Anti Spoofing private key as CMake options. - You can use either your own provisioning data or the provisioning data obtained by Nordic Semiconductor for development purposes. - The following debug devices are meant to be used with the nRF Desktop and have been registered: - - * NCS keyboard - The Fast Pair Provider meant to be used with keyboards: - - * Device Name: NCS keyboard - * Model ID: ``0x52FF02`` - * Anti-Spoofing Private Key (base64, uncompressed): ``8E8ulwhSIp/skZeg27xmWv2SxRxTOagypHrf2OdrhGY=`` - * Device Type: Input Device - * Notification Type: Fast Pair - * Data-Only connection: true - * No Personalized Name: false - - * NCS gaming mouse - Fast Pair Provider meant to be used with gaming mice: - - * Device Name: NCS gaming mouse - * Model ID: ``0x8E717D`` - * Anti-Spoofing Private Key (base64, uncompressed): ``dZxFzP7X9CcfLPC0apyRkmgsh3n2EbWo9NFNXfVuxAM=`` - * Device Type: Input Device - * Notification Type: Fast Pair - * Data-Only connection: true - * No Personalized Name: false - - See :ref:`ug_bt_fast_pair_provisioning` documentation for the following information: - - * Registering a Fast Pair Provider - * Provisioning a Fast Pair Provider in |NCS| - -.. nrf_desktop_fastpair_important_start - -.. important:: - This is the debug Fast Pair provisioning data obtained by Nordic for the development purposes. - It should not be used in production. - - To test with the debug mode Model ID, you must configure the Android device to include the debug results while displaying the nearby Fast Pair Providers. - For details, see `Verifying Fast Pair`_ in the GFPS documentation. - -.. nrf_desktop_fastpair_important_end - -.. _nrf_desktop_testing_steps: - -Testing -======= - -The application can be built and tested in various configurations. -The following procedure refers to the scenario where the gaming mouse (nRF52840 Gaming Mouse) and the keyboard (nRF52832 Desktop Keyboard) are connected simultaneously to the dongle (nRF52840 USB Dongle). - -After building the application with or without :ref:`specifying the build type `, test the nRF Desktop application by performing the following steps: - -1. Program the required firmware to each device. -#. Insert the :ref:`debug board or bypass board ` into the mouse to make sure it is powered. -#. Turn on both mouse and keyboard. - **LED1** on the keyboard and **LED1** on the mouse start breathing. -#. Plug the dongle to the USB port. - The blue **LED2** on the dongle starts breathing. - This indicates that the dongle is scanning for peripherals. -#. Wait for the establishment of the Bluetooth connection, which happens automatically. - After the Bluetooth connection is established, the LEDs stop breathing and remain turned on. - The devices can then be used simultaneously. - - .. note:: - You can manually start the scanning for new peripheral devices by pressing the **SW1** button on the dongle for a short time. - This might be needed if the dongle does not connect with all the peripherals before scanning is interrupted by a timeout. - -#. Move the mouse and press any key on the keyboard. - The input is reflected on the host. - - .. note:: - When a :ref:`configuration with debug features ` is enabled, for example logger and assertions, the gaming mouse report rate can be significantly lower. - - Make sure that you use the release configurations before testing the mouse report rate. - For the release configurations, you should observe a 500-Hz report rate when both the mouse and the keyboard are connected and a 1000-Hz rate when only the mouse is connected. - -#. Switch the Bluetooth peer on the gaming mouse by pressing the Precise Aim button (see `User interface`_). - The color of **LED1** changes from red to green and the LED starts blinking rapidly. -#. Press the Precise Aim button twice quickly to confirm the selection. - After the confirmation, **LED1** starts breathing and the mouse starts the Bluetooth advertising. -#. Connect to the mouse with an Android phone, a laptop, or any other Bluetooth Central. - -After the connection is established and the device is bonded, you can use the mouse with the connected device. - -.. _nrf_desktop_measuring_hid_report_rate: - -Measuring HID report rate -------------------------- - -You can measure a HID report rate of your application to assess the performance of your HID device. -This measurement allows you to check how often the host computer can get user's input from the HID device. - -Prerequsites -~~~~~~~~~~~~ - -The HID report rate can be measured by using either browser-based or platform-specific tools. -You can use any preferred HID report rate tool. - -.. note:: - The host computer controls polling a HID peripheral for HID reports. - The HID peripheral cannot trigger sending a HID report even if the report is prepared in time. - Polling inaccuracies and missing polls on the host side can negatively affect the measured report rate. - Make sure to close all unnecessary PC applications to mitigate negative impact of these applications on polling HID devices. - If you are using a browser-based tool, leave open only the tab with HID report rate measurement tool to ensure that no other tab influences the measurement. - -Building information -~~~~~~~~~~~~~~~~~~~~ - -Use the :file:`prj_release.conf` configuration for the HID report rate measurement. -Debug features, such as logging or assertions, decrease the application performance. - -Use the nRF Desktop configuration that acts as a HID mouse reference design for the report rate measurement, as the motion data polling is synchronized with sending HID reports. - -Make sure your chosen motion data source will generate movement in each poll interval. -Without a need for user's input, you can generate HID reports that contain mouse movement data. -To do this, use the :ref:`Motion simulated module `. - -To build an application for evaluating HID report rate, run the following command: - - .. parsed-literal:: - :class: highlight - - west build -p -b -- \ - -DCONF_FILE=prj_release.conf \ - -DCONFIG_DESKTOP_MOTION_SIMULATED_ENABLE=y \ - -Report rate measuring tips -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -See the following list of possible scenarios and best practices: - -* If two or more peripherals are connected through the dongle, and all of the devices support LLPM, then the Bluetooth LE LLPM connection events split evenly among all of the peripherals connected through that dongle. - It results in decreased HID report rate. - For example, you should observe a 500 Hz HID report rate when both mouse and keyboard are connected through the dongle and a 1000 Hz rate when only the mouse is connected. -* If a HID peripheral is connected through a dongle, the dongle's performance must be taken into account when measuring the report rate. - Delays related to data forwarding on the dongle also result in reduced report rate. -* If the device is connected through Bluetooth LE directly to the HID host, then the host sets the Bluetooth LE connection interval. - A Bluetooth LE peripheral can suggest the preferred connection parameters. - The suggested connection interval can be set using the :kconfig:option:`CONFIG_BT_PERIPHERAL_PREF_MIN_INT` and :kconfig:option:`CONFIG_BT_PERIPHERAL_PREF_MAX_INT` Kconfig options. - Set parameters are not enforced, meaning that the HID host may still eventually use a value greater than the maximum connection interval requested by a peripheral. -* Radio frequency (RF) noise can negatively affect the HID report rate for wireless connections. - If a HID report fails to be delivered in a given Bluetooth LE LLPM connection event, it is retransmitted in the subsequent connection event which effectively reduces the report rate. - By avoiding congested RF channels, the :ref:`nrf_desktop_ble_qos` helps to achieve better connection quality and a higher report rate. -* For the USB device connected directly, you can configure your preferred USB HID poll interval using the :kconfig:option:`CONFIG_USB_HID_POLL_INTERVAL_MS` Kconfig option. - By default, the :kconfig:option:`CONFIG_USB_HID_POLL_INTERVAL_MS` Kconfig option is set to ``1`` to request the lowest possible poll interval. - Set parameters are not enforced, meaning that the HID host may still eventually use a value greater than the USB polling interval requested by a peripheral. - -Testing steps -~~~~~~~~~~~~~ - -After building the application, test the nRF Desktop by performing the following steps: - -1. Program the device with the built firmware. -#. Connect the device to the computer using a preferred transport (Bluetooth LE, USB, dongle). -#. Turn on the device. - If you use the motion simulated module to generate the mouse movement, the device should automatically start to draw an octagon shape on the screen. - Otherwise, you need to constantly keep generating motion manually, for example, by moving your mouse. -#. Turn off the device to finalize test preparations. -#. Launch selected HID report rate measurement tool. -#. Turn back on the device. -#. Run measurement. -#. Verify the average HID report rate reported by tool. - -Windows Hardware Lab Kit tests ------------------------------- - -The nRF Desktop devices have passed the tests from official playlist required for compatibility with Windows 10 by Windows Hardware Compatibility Program (:file:`HLK Version 1903 CompatPlaylist x86 x64 ARM64.xml`). -The tests were conducted using `Windows Hardware Lab Kit`_. - - -.. _nrf_desktop_porting_guide: - -Integrating your own hardware -***************************** - -This section describes how to adapt the nRF Desktop application to different hardware. -It describes the configuration sources that are used for the default configuration, and lists steps required for adding a new board. - -Configuration sources -===================== - -The nRF Desktop application uses the following files as configuration sources: - -* Devicetree Specification (DTS) files - These reflect the hardware configuration. - See :ref:`zephyr:dt-guide` for more information about the DTS data structure. -* :file:`_def` files - These contain configuration arrays for the application modules and are specific to the nRF Desktop application. -* Kconfig files - These reflect the software configuration. - See :ref:`kconfig_tips_and_tricks` for information about how to configure them. - -For information about differences between DTS and Kconfig, see :ref:`zephyr:dt_vs_kconfig`. - -Application-specific Kconfig configuration -========================================== - -The nRF Desktop introduces Kconfig options that can be used to simplify an application configuration. -These options can be used to select a device role and to automatically apply a default configuration suitable for the selected role. - -.. note:: - Part of the default configuration is applied by modifying the default values of Kconfig options. - Changing configuration in menuconfig does not automatically adjust user-configurable values to the new defaults. - So, you must update those values manually. - For more information, see the Stuck symbols in menuconfig and guiconfig section on the :ref:`kconfig_tips_and_tricks` in the Zephyr documentation. - - The default Kconfig option values are automatically updated if configuration changes are applied directly in the configuration files. - -.. _nrf_desktop_hid_configuration: - -HID configuration ------------------ - -The nRF Desktop application introduces application-specific configuration options related to HID device configuration. -These options are defined in :file:`Kconfig.hid`. - -The options define the nRF Desktop device role. -The device role can be either the HID dongle (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) or the HID peripheral (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `). -The HID peripheral role can also specify a peripheral type: - -* HID mouse (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE `) -* HID keyboard (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_KEYBOARD `) -* other HID device (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_OTHER `) - -Each role automatically implies nRF Desktop modules needed for the role. -For example, :ref:`nrf_desktop_hid_state` is automatically enabled for the HID peripheral role. - -By default, the nRF Desktop devices use predefined format of HID reports. -The common HID report map is defined in the :file:`configuration/common/hid_report_desc.c` file. -The selected role implies a set of related HID reports. -For example, HID mouse automatically enables support for HID mouse report. -If ``other HID device`` peripheral type is chosen, the set of HID reports needs to be explicitly defined in the configuration. - -Apart from this, the supported HID boot protocol interface can be specified as either: - -* mouse (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE `) -* keyboard (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD `) -* none (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_DISABLED `) - -.. _nrf_desktop_hid_device_identifiers: - -HID device identifiers -~~~~~~~~~~~~~~~~~~~~~~ - -The nRF Desktop application defines the following common device identifiers: - -* Manufacturer (:ref:`CONFIG_DESKTOP_DEVICE_MANUFACTURER `) -* Vendor ID (:ref:`CONFIG_DESKTOP_DEVICE_VID `) -* Product name (:ref:`CONFIG_DESKTOP_DEVICE_PRODUCT `) -* Product ID (:ref:`CONFIG_DESKTOP_DEVICE_PID `) - -These Kconfig options determine the default values of device identifiers used for: - -* :ref:`nrf_desktop_usb_state_identifiers` -* BLE GATT Device Information Service (:kconfig:option:`CONFIG_BT_DIS`) that is required for :ref:`nrf_desktop_bluetooth_guide_peripheral` - -.. note:: - Apart from the mentioned common device identifiers, the nRF Desktop application defines an application-specific string representing device generation (:ref:`CONFIG_DESKTOP_DEVICE_GENERATION `). - The generation allows to distinguish configurations that use the same board and bootloader, but are not interoperable. - The value can be read through the :ref:`nrf_desktop_config_channel`. - -Debug configuration -------------------- - -The nRF Desktop application introduces application-specific configuration options related to the debug configuration. -These options are defined in the :file:`Kconfig.debug` file. - -The :ref:`CONFIG_DESKTOP_LOG ` Kconfig option enables support for logging in the nRF Desktop application. -This option overlays Kconfig option defaults from the Logging subsystem to align them with the nRF Desktop requirements. -The nRF Desktop configuration uses SEGGER J-Link RTT as the Logging subsystem backend. - -The :ref:`CONFIG_DESKTOP_SHELL ` Kconfig option enables support for CLI in the nRF Desktop application. -This option overlays Kconfig option defaults from the Shell subsystem to align them with the nRF Desktop requirements. -The nRF Desktop configuration uses SEGGER J-Link RTT as the Shell subsystem backend. -If both shell and logging are enabled, logger uses shell as the logging backend. - -See the :file:`Kconfig.debug` file content for details. - -Default common configuration ----------------------------- - -The nRF Desktop application aligns the configuration with the nRF Desktop use case by overlaying Kconfig defaults and selecting or implying the required Kconfig options. -Among others, the Kconfig :ref:`app_event_manager` and :ref:`lib_caf` options are selected to ensure that they are enabled. -The :ref:`CONFIG_DESKTOP_SETTINGS_LOADER ` and :ref:`CONFIG_DESKTOP_POWER_MANAGER ` are implied to enable the :ref:`nrf_desktop_settings_loader` and :ref:`nrf_desktop_power_manager` modules, respectively. -See the :file:`Kconfig.defaults` file for details related to default common configuration. - -.. _nrf_desktop_bluetooth_configuration: - -Bluetooth configuration ------------------------ - -The nRF Desktop application introduces application-specific configuration options related to Bluetooth connectivity configuration. -These options are defined in :file:`Kconfig.ble` file. - -The :ref:`CONFIG_DESKTOP_BT ` Kconfig option enables support for Bluetooth connectivity in the nRF Desktop application. -The option is enabled by default. - -The nRF Desktop Bluetooth peripheral configuration (:ref:`CONFIG_DESKTOP_BT_PERIPHERAL `) is automatically enabled for the nRF Desktop HID peripheral role (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `). -The nRF Desktop Bluetooth central configuration (:ref:`CONFIG_DESKTOP_BT_CENTRAL `) is automatically enabled for the nRF Desktop HID dongle role (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) - -The nRF Desktop Bluetooth configuration options perform the following: - -* Implies application modules related to Bluetooth that are required for the selected device role -* Selects required functionalities in Zephyr's Bluetooth stack -* Overlays Bluetooth Kconfig option defaults to align them with the nRF Desktop use-case - -See :file:`Kconfig.ble` file content for details. -See the :ref:`nrf_desktop_bluetooth_guide` for more information about Bluetooth support in nRF Desktop application. - -CAF configuration ------------------ - -The nRF Desktop application overlays defaults of the :ref:`lib_caf` related Kconfig options to align them with the nRF Desktop use-case. -The files that apply the overlays are located in the :file:`src/modules` directory and are named :file:`Kconfig.caf_module_name.default`. -For example, the Kconfig defaults of :ref:`caf_settings_loader` are overlayed in the :file:`src/modules/Kconfig.caf_settings_loader.default`. - -.. _nrf_desktop_board_configuration: - -Board configuration -=================== - -The nRF Desktop application is modular. -Depending on requested functions, it can provide mouse, keyboard, or dongle functionality. -The selection of modules depends on the chosen role and also on the selected reference design. -For more information about modules available for each configuration, see :ref:`nrf_desktop_architecture`. - -For a board to be supported by the application, you must provide a set of configuration files at :file:`applications/nrf_desktop/configuration/your_board_name`. -The application configuration files define both a set of options with which the nRF Desktop application will be created for your board and the selected :ref:`nrf_desktop_requirements_build_types`. -Include the following files in this directory: - -Mandatory configuration files - * Application configuration file for the :ref:`debug build type ` (:file:`prj.conf`). - * Configuration files for the selected modules. - -Optional configuration files - * Application configuration files for other build types. - * Configuration file for the bootloader. - * Memory layout configuration. - * DTS overlay file. - -See `Adding a new board`_ for information about how to add these files. - -.. _nrf_desktop_board_configuration_files: - -nRF Desktop board configuration files -------------------------------------- - -The nRF Desktop application comes with configuration files for the following reference designs: - -nRF52840 Gaming Mouse (nrf52840gmouse_nrf52840) - * The reference design is defined in :file:`nrf/boards/arm/nrf52840gmouse_nrf52840` for the project-specific hardware. - * To achieve gaming-grade performance: - - * The application is configured to act as a gaming mouse, with both Bluetooth LE and USB transports enabled. - * Bluetooth is configured to use Nordic's SoftDevice link layer. - - * The configuration with the B0 bootloader is set as default. - * The board supports debug (:file:`prj_fast_pair.conf`) and release (:file:`prj_release_fast_pair.conf`) :ref:`nrf_desktop_bluetooth_guide_fast_pair` configurations. - Both configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and they support the firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. - -nRF52832 Desktop Mouse (nrf52dmouse_nrf52832) and nRF52810 Desktop Mouse (nrf52810dmouse_nrf52810) - * Both reference designs are meant for the project-specific hardware and are defined in :file:`nrf/boards/arm/nrf52dmouse_nrf52832` and :file:`nrf/boards/arm/nrf52810dmouse_nrf52810`, respectively. - * The application is configured to act as a mouse. - * Only the Bluetooth LE transport is enabled. - Bluetooth uses either Zephyr's software link layer (nrf52810dmouse_nrf52810) or Nordic's SoftDevice link layer (nrf52dmouse_nrf52832). - * The preconfigured build types for both nrf52dmouse_nrf52832 and nrf52810dmouse_nrf52810 boards are without the bootloader due to memory size limits on nrf52810dmouse_nrf52810 board. - -Sample mouse, keyboard or dongle (nrf52840dk_nrf52840) - * The configuration uses the nRF52840 Development Kit. - * The build types allow to build the application as mouse, keyboard or dongle. - * Inputs are simulated based on the hardware button presses. - * The configuration with the B0 bootloader is set as default. - * The board supports debug :ref:`nrf_desktop_bluetooth_guide_fast_pair` configuration that acts as a mouse (:file:`prj_fast_pair.conf`). - The configuration uses the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and supports firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. - -Sample dongle (nrf52833dk_nrf52833) - * The configuration uses the nRF52833 Development Kit. - * The application is configured to act as a dongle that forwards data from both mouse and keyboard. - * Bluetooth uses Nordic's SoftDevice link layer and is configured to act as a central. - Input data comes from Bluetooth and is retransmitted to USB. - * The configuration with the MCUboot bootloader is set as default. - -Sample dongle (nrf52833dk_nrf52820) - * The configuration uses the nRF52820 emulation on the nRF52833 Development Kit. - * The application is configured to act as a dongle that forwards data from both mouse and keyboard. - * Bluetooth uses Zephyr's software link layer and is configured to act as a central. - Input data comes from Bluetooth and is retransmitted to USB. - * |preconfigured_build_types| - -nRF52832 Desktop Keyboard (nrf52kbd_nrf52832) - * The reference design used is defined in :file:`nrf/boards/arm/nrf52kbd_nrf52832` for the project-specific hardware. - * The application is configured to act as a keyboard, with the Bluetooth LE transport enabled. - * Bluetooth is configured to use Nordic's SoftDevice link layer. - * The preconfigured build types configure the device without the bootloader in debug mode and with B0 bootloader in release mode due to memory size limits. - * The board supports release :ref:`nrf_desktop_bluetooth_guide_fast_pair` configuration (:file:`prj_release_fast_pair.conf`). - The configuration uses the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and supports firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. - -nRF52840 USB Dongle (nrf52840dongle_nrf52840) and nRF52833 USB Dongle (nrf52833dongle_nrf52833) - * Since the nRF52840 Dongle is generic and defined in Zephyr, project-specific changes are applied in the DTS overlay file. - * The application is configured to act as a dongle that forwards data from both mouse and keyboard. - * Bluetooth uses Nordic's SoftDevice link layer and is configured to act as a central. - Input data comes from Bluetooth and is retransmitted to USB. - * The configuration with the B0 bootloader is set as default for nrf52840dongle_nrf52840 board and with the MCUboot bootloader is set as default for nrf52833dongle_nrf52833 board. - -nRF52820 USB Dongle (nrf52820dongle_nrf52820) - * The application is configured to act as a dongle that forwards data from both mouse and keyboard. - * Bluetooth uses Zephyr's software link layer and is configured to act as a central. - Input data comes from Bluetooth and is retransmitted to USB. - * |preconfigured_build_types| - -Sample dongle (nrf5340dk_nrf5340) - * The application is configured to act as a dongle that forwards data from both mouse and keyboard. - * Bluetooth uses Nordic's SoftDevice link layer without LLPM and is configured to act as a central. - Input data comes from Bluetooth and is retransmitted to USB. - * The configuration with the B0 bootloader is set as default. - -.. _porting_guide_adding_board: - -Adding a new board -================== - -When adding a new board for the first time, focus on a single configuration. -Moreover, keep the default debug build type that the application is built with, and do not add any additional build type parameters. -The following procedure uses the gaming mouse configuration as an example. - -Zephyr support for a board --------------------------- - -Before introducing nRF Desktop application configuration for a given board, you need to ensure that the board is supported in Zephyr. - -.. note:: - You can skip this step if your selected board is already supported in Zephyr. - -Follow the Zephyr's :ref:`zephyr:board_porting_guide` for detailed instructions related to introducing Zephyr support for a new board. -Make sure that the following conditions are met: - -#. Edit the DTS files to make sure they match the hardware configuration. - Pay attention to the following elements: - - * Pins that are used. - * Bus configuration for optical sensor. - * `Changing interrupt priority`_. - -#. Edit the board's Kconfig files to make sure they match the required system configuration. - For example, disable the drivers that will not be used by your device. - -.. tip:: - You can define the new board by copying the nRF Desktop reference design files that are the closest match for your hardware and then aligning the configuration to your hardware. - For example, for gaming mouse use :file:`nrf/boards/arm/nrf52840gmouse_nrf52840`. - -nRF Desktop configuration -------------------------- - -Perform the following steps to add nRF Desktop application configuration for a board that is already supported in Zephyr. - -1. Copy the project files for the device that is the closest match for your hardware. - For example, for gaming mouse these are located at :file:`applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840`. -#. Optionally, depending on the reference design, edit the DTS overlay file. - This step is not required if you have created a new reference design and its DTS files fully describe your hardware. - In such case, the overlay file can be left empty. -#. In Kconfig, ensure that the following hardware interface modules that are specific for gaming mouse are enabled: - - * :ref:`caf_buttons` - * :ref:`caf_leds` - * :ref:`nrf_desktop_motion` - * :ref:`nrf_desktop_wheel` - * :ref:`nrf_desktop_battery_meas` - -#. For each module enabled, change its configuration to match your hardware. - Apply the following changes, depending on the module: - - Motion module - * The ``nrf52840gmouse_nrf52840`` uses the PMW3360 optical motion sensor. - The sensor is configured in DTS, and the sensor type is selected in the application configuration. - To add a new sensor, expand the application configuration. - Wheel module - * The wheel is based on the QDEC peripheral of the nRF52840 device and the hardware-related part is configured in DTS. - Buttons module - * To simplify the configuration of arrays, the nRF Desktop application uses :file:`_def` files. - * The :file:`_def` file of the buttons module contains pins assigned to rows and columns. - Battery measurement module - * The :file:`_def` file of the battery measurement module contains the mapping needed to match the voltage that is read from ADC to the battery level. - LEDs module - * The application uses two logical LEDs - one for the peers state, and one for the system state indication. - * Each of the logical LEDs can have either one (monochromatic) or three color channels (RGB). - Such color channel is a physical LED. - * The module uses Zephyr's :ref:`zephyr:led_api` driver for setting the LED color. - Zephyr's LED driver can use the implementation based on either GPIO or PWM (Pulse-Width Modulation). - The hardware configuration is described through DTS. - See the :ref:`caf_leds` configuration section for details. - -#. Review the :ref:`nrf_desktop_hid_configuration`. -#. By default, the nRF Desktop device enables Bluetooth connectivity support. - Review the :ref:`nrf_desktop_bluetooth_configuration`. - - a. Ensure that the Bluetooth role is properly configured. - For mouse, it should be configured as peripheral. - #. Update the configuration related to peer control. - You can also disable the peer control using the :ref:`CONFIG_DESKTOP_BLE_PEER_CONTROL ` option. - Peer control details are described in the :ref:`nrf_desktop_ble_bond` documentation. - -#. Edit Kconfig to disable options that you do not use. - Some options have dependencies that might not be needed when these options are disabled. - For example, when the LEDs module is disabled, the PWM driver is not needed. - -.. _porting_guide_adding_sensor: - -Adding a new motion sensor -========================== - -This procedure describes how to add a new motion sensor into the project. -You can use it as a reference for adding other hardware components. - -The nRF Desktop application comes with a :ref:`nrf_desktop_motion` that is able to read data from a motion sensor. -While |NCS| provides support for two motion sensor drivers (PMW3360 and PAW3212), you can add support for a different sensor, based on your development needs. - -Complete the steps described in the following sections to add a new motion sensor. - -.. rst-class:: numbered-step - -Add a new sensor driver ------------------------ - -First, create a new motion sensor driver that will provide code for communication with the sensor. -Use the two existing |NCS| sensor drivers as an example. - -The communication between the application and the sensor is done through a sensor driver API (see :ref:`sensor_api`). -For the motion module to work correctly, the driver must support a trigger (see ``sensor_trigger_set``) on a new data (see ``SENSOR_TRIG_DATA_READY`` trigger type). - -When the motion data is ready, the driver calls a registered callback. -The application starts a process of retrieving a motion data sample. -The motion module calls ``sensor_sample_fetch`` and then ``sensor_channel_get`` on two sensor channels, ``SENSOR_CHAN_POS_DX`` and ``SENSOR_CHAN_POS_DY``. -The driver must support these two channels. - -.. rst-class:: numbered-step - -Create a DTS binding --------------------- - -Zephyr recommends to use DTS for hardware configuration (see :ref:`zephyr:dt_vs_kconfig`). -For the new motion sensor configuration to be recognized by DTS, define a dedicated DTS binding. -See :ref:`dt-bindings` for more information, and refer to :file:`dts/bindings/sensor` for binding examples. - -.. rst-class:: numbered-step - -Configure sensor through DTS ----------------------------- - -Once binding is defined, it is possible to set the sensor configuration. -This is done by editing the DTS file that describes the board. -For more information, see :ref:`devicetree-intro`. - -As an example, take a look at the PMW3360 sensor that already exists in |NCS|. -The following code excerpt is taken from :file:`boards/arm/nrf52840gmouse_nrf52840/nrf52840gmouse_nrf52840.dts`: - -.. code-block:: none - - &spi1 { - compatible = "nordic,nrf-spim"; - status = "okay"; - cs-gpios = <&gpio0 13 0>; - - pinctrl-0 = <&spi1_default_alt>; - pinctrl-1 = <&spi1_sleep_alt>; - pinctrl-names = "default", "sleep"; - pmw3360@0 { - compatible = "pixart,pmw3360"; - reg = <0>; - irq-gpios = <&gpio0 21 0>; - spi-max-frequency = <2000000>; - }; - }; - -The communication with PMW3360 is done through the SPI, which makes the sensor a subnode of the SPI bus node. -SPI pins are defined as part of the bus configuration, as these are common among all devices connected to this bus. -In this case, the PMW3360 sensor is the only device on this bus and so there is only one pin specified for selecting chip. - -When the sensor's node is mentioned, you can read ``@0`` in ``pmw3360@0``. -For SPI devices, ``@0`` refers to the position of the chip select pin in the ``cs-gpios`` array for a corresponding device. - -Note the string ``compatible = "pixart,pmw3360"`` in the subnode configuration. -This string indicates which DTS binding the node will use. -The binding should match with the DTS binding created earlier for the sensor. - -The following options are inherited from the ``spi-device`` binding and are common to all SPI devices: - -* ``reg`` - The slave ID number the device has on a bus. -* ``label`` - Used to generate a name of the device (for example, it will be added to generated macros). -* ``spi-max-frequency`` - Used for setting the bus clock frequency. - - .. note:: - To achieve the full speed, data must be propagated through the application and reach Bluetooth LE a few hundred microseconds before the subsequent connection event. - If you aim for the lowest latency through the LLPM (an interval of 1 ms), the sensor data readout should take no more than 250 us. - The bus and the sensor configuration must ensure that communication speed is fast enough. - -The remaining option ``irq-gpios`` is specific to ``pixart,pmw3360`` binding. -It refers to the PIN to which the motion sensor IRQ line is connected. - -If a different kind of bus is used for the new sensor, the DTS layout will be different. - -.. rst-class:: numbered-step - -Include sensor in the application ---------------------------------- - -Once the new sensor is supported by |NCS| and board configuration is updated, you can include it in the nRF Desktop application. - -The nRF Desktop application selects a sensor using the configuration options defined in :file:`src/hw_interface/Kconfig.motion`. -Add the new sensor as a new choice option. - -The :ref:`nrf_desktop_motion` of the nRF Desktop application has access to several sensor attributes. -These attributes are used to modify the sensor behavior in runtime. -Since the names of the attributes differ for each sensor, the :ref:`nrf_desktop_motion` uses a generic abstraction of them. -You can translate the new sensor-specific attributes to a generic abstraction by modifying :file:`configuration/common/motion_sensor.h` . +The nRF Desktop is a reference design of a :term:`Human Interface Device (HID)` that is connected to a host through Bluetooth® Low Energy or USB, or both. +Depending on the configuration, this application can work as a desktop mouse, gaming mouse, keyboard, or connection dongle. +See `nRF Desktop reference design page`_ for an overview of supported features. .. tip:: - If an attribute is not supported by the sensor, it does not have to be defined. - In such case, set the attribute to ``-ENOTSUP``. - -.. rst-class:: numbered-step - -Select the new sensor ---------------------- - -The application can now use the new sensor. -Edit the application configuration files for your board to enable it. -See :ref:`nrf_desktop_board_configuration` for details. - -To start using the new sensor, complete the following steps: - -1. Enable all dependencies required by the driver (for example, bus driver). -#. Enable the new sensor driver. -#. Select the new sensor driver in the application configuration options. - -Changing interrupt priority ---------------------------- - -You can edit the DTS files to change the priority of the peripheral's interrupt. -This can be useful when :ref:`adding a new custom board ` or whenever you need to change the interrupt priority. - -The ``interrupts`` property is an array, where the meaning of each element is defined by the specification of the interrupt controller. -These specification files are located at :file:`zephyr/dts/bindings/interrupt-controller/` DTS binding file directory. - -For example, for nRF52840 the file is :file:`arm,v7m-nvic.yaml`. -This file defines ``interrupts`` property in the ``interrupt-cells`` list. -For nRF52840, it contains two elements: ``irq`` and ``priority``. -The default values for these elements for the given peripheral can be found in the :file:`dtsi` file specific for the device. -In the case of nRF52840, this is :file:`zephyr/dts/arm/nordic/nrf52840.dtsi`, which has the following ``interrupts``: - -.. code-block:: - - spi1: spi@40004000 { - /* - * This spi node can be SPI, SPIM, or SPIS, - * for the user to pick: - * compatible = "nordic,nrf-spi" or - * "nordic,nrf-spim" or - * "nordic,nrf-spis". - */ - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40004000 0x1000>; - interrupts = <4 1>; - status = "disabled"; - }; - -To change the priority of the peripheral's interrupt, override the ``interrupts`` property of the peripheral node by including the following code snippet in the :file:`dts.overlay` or directly in the board DTS: - -.. code-block:: none - - &spi1 { - interrupts = <4 2>; - }; - -This code snippet will change the **SPI1** interrupt priority from default ``1`` to ``2``. - -.. _nrf_desktop_memory_layout: - -Memory layout -============= - -You must define the memory layout as a part of the application configuration for a given board. -The set of required partitions differs depending on configuration: - -* There must be at least one partition where the code is stored. -* There must be one partition for storing :ref:`zephyr:settings_api`. -* If the bootloader is enabled, it adds more partitions to the set. -* When using an SoC with multiple cores, the firmware for additional cores adds more partitions to the set. - For example, the network core of the nRF53 SoC uses the ``HCI RPMsg`` firmware image, which allows to utilize the core for Bluetooth LE communication. - -.. important:: - Before updating the firmware, make sure that the data stored in the settings partition is compatible with the new firmware. - If it is incompatible, erase the settings area before using the new firmware. - -The memory layout is defined through one of the following methods: - -* `Memory layout in DTS`_ -* `Memory layout in Partition Manager`_ - -By default, a Zephyr-based application defines the memory layout in the DTS. -If enabled, the :ref:`partition_manager` defines a new memory layout that is used instead of the memory layout defined in the DTS. -You can use the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` Kconfig option value to check whether the Partition Manager is enabled in the current build. -The option is automatically selected as part of the :ref:`ug_multi_image` feature to build the application with more than one image. -Enabling the :ref:`nrf_desktop_bluetooth_guide_fast_pair` also results in using the Partition Manager. -To store the Fast Pair Provisioning data, the Fast Pair integration in the |NCS| uses partition defined by the Partition Manager. - -Memory layout in DTS --------------------- - -In case you rely on a non-volatile memory layout described in DTS files, define the ``partitions`` child node under the DTS node that represents the non-volatile memory. -For example, the nRF52 Series devices use non-volatile flash memory represented by the flash device node (``&flash0``). -Make sure to also update the DTS chosen nodes, which represent the code partition (``zephyr,code-partition``) and flash (``zephyr,flash``), if needed. - -If you wish to change the default memory layout of the board without editing the board-specific files, edit the DTS overlay file. -The nRF Desktop application automatically adds the :file:`dts.overlay` file if it is present in the project's board configuration directory. -For more details, see the `Board configuration`_ section. - -.. important:: - By default, Zephyr does not use the code partition defined in the DTS files. - It is only used if the :kconfig:option:`CONFIG_USE_DT_CODE_PARTITION` Kconfig option is enabled. - If this option is disabled, the code is loaded at the offset defined by the :kconfig:option:`CONFIG_FLASH_LOAD_OFFSET` Kconfig option. - In that case, the code spawns for :kconfig:option:`CONFIG_FLASH_LOAD_SIZE` (or for the whole remaining chosen ``zephyr,flash`` memory if the load size is set to ``0``). - The settings memory partition definition is still used by the firmware even if the :kconfig:option:`CONFIG_USE_DT_CODE_PARTITION` Kconfig option is disabled. - -For more information about how to configure the non-volatile memory layout in the DTS files, see :ref:`zephyr:flash_map_api`. - -Memory layout in Partition Manager ----------------------------------- - -When the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` Kconfig option is enabled, the nRF Desktop application uses the Partition Manager for the memory layout configuration. -The nRF Desktop configurations use static configurations of partitions to ensure that the partition layout will not change between builds. - -Add the :file:`pm_static_${BUILD_TYPE}.yml` file to the project's board configuration directory to define the static Partition Manager configuration for given board and build type. -For example, to define the static partition layout for the nrf52840dk_nrf52840 board and release build type, you would need to add the :file:`pm_static_release.yml` file into the :file:`applicatons/nrf_desktop/configuration/nrf52840dk_nrf52840` directory. - -Take into account the following points: - -* For the :ref:`background firmware upgrade `, you must define the secondary image partition. - This is because the update image is stored on the secondary image partition while the device is running firmware from the primary partition. - For this reason, the feature is not available for devices with smaller non-volatile memory size, because the size of the required non-volatile memory is essentially doubled. - The devices with smaller non-volatile memory size can use either USB serial recovery or the MCUboot bootloader with the secondary image partition located on an external non-volatile memory. -* When you use :ref:`USB serial recovery `, you do not need the secondary image partition. - The firmware image is overwritten by the bootloader. - -For an example of configuration, see the static partition maps defined for the existing configuration that uses a given DFU method. -For more information about how to configure the non-volatile memory layout using the Partition Manager, see :ref:`partition_manager`. - -.. _nrf_desktop_pm_external_flash: - -External flash configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Partition Manager supports partitions in external flash. - -Enabling external flash can be useful especially for memory-limited devices. -For example, the MCUboot can use it as a secondary image partition for the :ref:`background firmware upgrade `. -The MCUboot moves the image data from the secondary image partition to the primary image partition before booting the new firmware. - -For an example of the nRF Desktop application configuration that uses an external flash, see the ``mcuboot_qspi`` configuration of the nRF52840 Development Kit. -This configuration uses the ``MX25R64`` external flash that is part of the development kit. - -For detailed information, see the :ref:`partition_manager` documentation. - -.. _nrf_desktop_bluetooth_guide: - -Bluetooth in nRF Desktop -======================== - -The nRF Desktop devices use :ref:`Zephyr's Bluetooth API ` to handle the Bluetooth LE connections. - -This API is used only by the application modules that handle such connections. -The information about peer and connection state is propagated to other application modules using :ref:`app_event_manager` events. - -The :ref:`CONFIG_DESKTOP_BT ` Kconfig option enables support for Bluetooth connectivity in the nRF Desktop. -Specific Bluetooth configurations and application modules are selected or implied according to the HID device role. -Apart from that, the defaults of Bluetooth-related Kconfigs are aligned with the nRF Desktop use case. - -The nRF Desktop devices come in the following roles: - -* HID peripheral (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `) that works as Bluetooth Peripheral (:ref:`CONFIG_DESKTOP_BT_PERIPHERAL `) - - * Support only the Bluetooth Peripheral role (:kconfig:option:`CONFIG_BT_PERIPHERAL`). - * Handle only one Bluetooth LE connection at a time. - * Use more than one Bluetooth local identity. - -* HID dongle (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) that works as Bluetooth Central (:ref:`CONFIG_DESKTOP_BT_CENTRAL `) - - * Support only the Bluetooth Central role (:kconfig:option:`CONFIG_BT_CENTRAL`). - * Handle multiple Bluetooth LE connections simultaneously. - * Use only one Bluetooth local identity (the default one). - -Both central and peripheral devices have dedicated configuration options and use dedicated modules. - -The nRF Desktop peripheral configurations that enable `Fast Pair`_ support use slightly different Bluetooth configuration. -This is needed to improve the user experience. -See :ref:`nrf_desktop_bluetooth_guide_fast_pair` for more details. - -.. note:: - There is no nRF Desktop device that supports both central and peripheral roles. - -Common configuration and application modules --------------------------------------------- - -Some Bluetooth-related :ref:`configuration options ` (including :ref:`nrf_desktop_bluetooth_guide_configuration_ll` in a separate section) and :ref:`application modules ` are common for every nRF Desktop device. - -.. _nrf_desktop_bluetooth_guide_configuration: - -Configuration options -~~~~~~~~~~~~~~~~~~~~~ - -This section describes the most important Bluetooth Kconfig options common for all nRF Desktop devices. -For detailed information about every option, see the Kconfig help. - -* :kconfig:option:`CONFIG_BT_MAX_PAIRED` - - * nRF Desktop central: The maximum number of paired devices is greater than or equal to the maximum number of simultaneously connected peers. - The :kconfig:option:`CONFIG_BT_MAX_PAIRED` is by default set to :ref:`CONFIG_DESKTOP_HID_DONGLE_BOND_COUNT `. - * nRF Desktop peripheral: The maximum number of paired devices is equal to the number of peers plus one, where the one additional paired device slot is used for erase advertising. - -* :kconfig:option:`CONFIG_BT_ID_MAX` - - * nRF Desktop central: The device uses only one Bluetooth local identity, that is the default one. - * nRF Desktop peripheral: The number of Bluetooth local identities must be equal to the number of peers plus two. - - * One additional local identity is used for erase advertising. - * The other additional local identity is the default local identity, which is unused, because it cannot be reset after removing the bond. - Without the identity reset, the previously bonded central could still try to reconnect after being removed from Bluetooth bonds on the peripheral side. - -* :kconfig:option:`CONFIG_BT_MAX_CONN` - - * nRF Desktop central: This option is set to the maximum number of simultaneously connected devices. - The :kconfig:option:`CONFIG_BT_MAX_CONN` is by default set to :ref:`CONFIG_DESKTOP_HID_DONGLE_CONN_COUNT `. - * nRF Desktop peripheral: The default value (one) is used. - -.. note:: - After changing the number of Bluetooth peers for the nRF Desktop peripheral device, update the LED effects used to represent the Bluetooth connection state. - For details, see :ref:`nrf_desktop_led_state`. - -.. _nrf_desktop_bluetooth_guide_configuration_ll: - -Link Layer configuration options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The nRF Desktop devices use one of the following Link Layers: - -* :kconfig:option:`CONFIG_BT_LL_SW_SPLIT` - This Link Layer does not support the Low Latency Packet Mode (LLPM) and has a lower memory usage, so it can be used by memory-limited devices. - -* :kconfig:option:`CONFIG_BT_LL_SOFTDEVICE` - This Link Layer does support the Low Latency Packet Mode (LLPM). - If you opt for this Link Layer and enable the :kconfig:option:`CONFIG_BT_CTLR_SDC_LLPM`, the :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is also enabled by default and can be configured further: - - * When :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is enabled, set the value for :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``3000``. - - This is required by the nRF Desktop central and helps avoid scheduling conflicts with Bluetooth Link Layer. - Such conflicts could lead to a drop in HID input report rate or a disconnection. - Because of this, if the nRF Desktop central supports LLPM and more than one simultaneous Bluetooth connection, it also uses 10 ms connection interval instead of 7.5 ms. - Setting the value of :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``3000`` also enables the nRF Desktop central to exchange data with up to 3 standard Bluetooth LE peripherals during every connection interval (every 10 ms). - - * When :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is disabled, the device will use only standard Bluetooth LE connection parameters with the lowest available connection interval of 7.5 ms. - - If the LLPM is disabled and more than 2 simultaneous Bluetooth connections are supported (:kconfig:option:`CONFIG_BT_MAX_CONN`), you can set the value for :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``2500``. - With this value, the nRF Desktop central is able to exchange the data with up to 3 Bluetooth LE peripherals during every 7.5-ms connection interval. - Using the value of ``3000`` for more than 2 simultaneous Bluetooth LE connections will result in a lower HID input report rate. - -.. _nrf_desktop_bluetooth_guide_modules: - -Application modules -~~~~~~~~~~~~~~~~~~~ - -Every nRF Desktop device that enables Bluetooth must handle connections and manage bonds. -These features are implemented by the following modules: - -* :ref:`nrf_desktop_ble_state` - Enables Bluetooth and LLPM (if supported), and handles Zephyr connection callbacks. -* :ref:`nrf_desktop_ble_bond` - Manages Bluetooth bonds and local identities. - -You need to enable all these modules to enable both features. -For information about how to enable the modules, see their respective documentation pages. - -Optionally, you can also enable the following module: - -* :ref:`nrf_desktop_ble_qos` - Helps achieve better connection quality and higher report rate. - The module can be used only with the SoftDevice Link Layer. - -.. note:: - The nRF Desktop devices enable :kconfig:option:`CONFIG_BT_SETTINGS`. - When this option is enabled, the application is responsible for calling the :c:func:`settings_load` function - this is handled by the :ref:`nrf_desktop_settings_loader`. - -.. _nrf_desktop_bluetooth_guide_peripheral: - -Bluetooth Peripheral --------------------- - -The nRF Desktop peripheral devices must include additional configuration options and additional application modules to comply with the HID over GATT specification. - -The HID over GATT profile specification requires Bluetooth Peripherals to define the following GATT Services: - -* HID Service - Handled in the :ref:`nrf_desktop_hids`. -* Battery Service - Handled in the :ref:`nrf_desktop_bas`. -* Device Information Service - Implemented in Zephyr and enabled with :kconfig:option:`CONFIG_BT_DIS`. - The device identifiers are configured according to the common :ref:`nrf_desktop_hid_device_identifiers` by default. - It can be configured using Kconfig options with the ``CONFIG_BT_DIS`` prefix. - -The nRF Desktop peripherals must also define a dedicated GATT Service, which is used to provide the following information: - -* Information whether the device can use the LLPM Bluetooth connection parameters. -* Hardware ID of the peripheral. - -The GATT Service is implemented by the :ref:`nrf_desktop_dev_descr`. - -Apart from the GATT Services, an nRF Desktop peripheral device must enable and configure the following application modules: - -* :ref:`nrf_desktop_ble_adv` - Controls the Bluetooth advertising. -* :ref:`nrf_desktop_ble_latency` - Keeps the connection latency low when the :ref:`nrf_desktop_config_channel` is used or when either the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr` receive an update image. - This is done to ensure quick data transfer. - -Optionally, you can also enable the following module: - -* :ref:`nrf_desktop_qos` - Forwards the Bluetooth LE channel map generated by :ref:`nrf_desktop_ble_qos`. - The Bluetooth LE channel map is forwarded using GATT characteristic. - The Bluetooth Central can apply the channel map to avoid congested RF channels. - This results in better connection quality and higher report rate. - -.. _nrf_desktop_bluetooth_guide_fast_pair: - -Fast Pair -~~~~~~~~~ - -The nRF Desktop peripheral can be built with Google `Fast Pair`_ support. -The configurations that enable Fast Pair are set in the :file:`prj_fast_pair.conf` and :file:`prj_release_fast_pair.conf` files. - -.. note:: - The Fast Pair integration in the nRF Desktop is :ref:`experimental `. - The factory reset of the Fast Pair non-volatile data is not yet supported. - - The Fast Pair support in the |NCS| is :ref:`experimental `. - See :ref:`ug_bt_fast_pair` for details. - -These configurations support multiple bonds per Bluetooth local identity (:kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS` is set to ``3``) and erase advertising (:ref:`CONFIG_DESKTOP_BLE_PEER_ERASE `), but Bluetooth peer selection (:ref:`CONFIG_DESKTOP_BLE_PEER_SELECT `) is disabled. -You can now pair with your other hosts without putting peripheral back in pairing mode (without triggering the erase advertising). -The nRF Desktop peripheral that integrates Fast Pair behaves as follows: - - * The dongle peer does not use the Fast Pair advertising payload. - * The bond erase operation is enabled for the dongle peer. - This will let you change the bonded Bluetooth Central. - * If the dongle peer (:ref:`CONFIG_DESKTOP_BLE_DONGLE_PEER_ENABLE `) is enabled, the `Swift Pair`_ payload is, by default, included only for the mentioned peer. - In the Fast Pair configurations, the dongle peer is intended to be used for all of the peers that are not Fast Pair Seekers. - * If the used Bluetooth local identity has no bonds, the device advertises in pairing mode, and the Fast Pair discoverable advertising is used. - This allows to pair with the nRF Desktop device using both Fast Pair and normal Bluetooth pairing flows. - This advertising payload is also used during the erase advertising. - * If the used Bluetooth local identity already has a bond, the device is no longer in the pairing mode and the Fast Pair not discoverable advertising is used. - This allows to pair only with the Fast Pair Seekers linked to Google Accounts that are already associated with the nRF Desktop device. - In this mode the device by default rejects normal Bluetooth pairing (:ref:`CONFIG_DESKTOP_FAST_PAIR_LIMIT_NORMAL_PAIRING ` option is enabled). - The Fast Pair UI indication is hidden after the Provider reaches :kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS` bonded peers on the used local identity. - * The :ref:`nrf_desktop_factory_reset` is enabled by default if the :ref:`nrf_desktop_config_channel` is supported by the device. - The factory reset operation removes both Fast Pair and Bluetooth non-volatile data. - The factory reset operation is triggered using the configuration channel. - -After successful erase advertising procedure, the peripheral removes all of the bonds of a given Bluetooth local identity. - -Apart from that, the following changes are applied in configurations that support Fast Pair: - -* The static :ref:`partition_manager` configuration is modified to introduce a dedicated non-volatile memory partition used to store the Fast Pair provisioning data. -* Bluetooth privacy feature (:kconfig:option:`CONFIG_BT_PRIVACY`) is enabled. -* The fast and slow advertising intervals defined in the :ref:`nrf_desktop_ble_adv` are aligned with Fast Pair expectations. -* The Bluetooth advertising filter accept list (:kconfig:option:`CONFIG_CAF_BLE_ADV_FILTER_ACCEPT_LIST`) is disabled to allow Fast Pair Seekers other than the bonded one to connect outside of the pairing mode. -* The security failure timeout (:ref:`CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S `) is longer to prevent disconnections during the Fast Pair procedure. -* Passkey authentication (:ref:`CONFIG_DESKTOP_BLE_ENABLE_PASSKEY `) is disabled on keyboard. - Fast Pair currently does not support devices that use screen or keyboard for Bluetooth authentication. -* TX power correction value (:kconfig:option:`CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL`) is configured to align the TX power included in the advertising data with the Fast Pair expectations. - -See :ref:`ug_bt_fast_pair` for detailed information about Fast Pair support in the |NCS|. - -Bluetooth Central ------------------ - -The nRF Desktop central must implement Bluetooth scanning and handle the GATT operations. -The central must also control the Bluetooth connection parameters. -These features are implemented by the following application modules: - -* :ref:`nrf_desktop_ble_scan` - Controls the Bluetooth scanning. -* :ref:`nrf_desktop_ble_conn_params` - Controls the Bluetooth connection parameters and reacts on latency update requests received from the connected peripherals. -* :ref:`nrf_desktop_ble_discovery` - Handles discovering and reading the GATT Characteristics from the connected peripheral. -* :ref:`nrf_desktop_hid_forward` - Subscribes for HID reports from the Bluetooth Peripherals (HID over GATT) and forwards data using application events. - -.. _nrf_desktop_bootloader: - -Bootloader -========== - -The nRF Desktop application can use one of the following bootloaders: - -**Secure Bootloader** - In this documentation, the Secure Bootloader is referred as *B0*. - B0 is a small, simple, and secure bootloader that allows the application to boot directly from one of the application slots, thus increasing the speed of the direct firmware upgrade (DFU) process. - B0 is supported on the SoCs from the following series: - - * nRF52 Series - * nRF53 Series (supports only application core DFU) - - This bootloader can be used only for the :ref:`background DFU ` through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. - More information about the B0 can be found at the :ref:`bootloader` page. - -**MCUboot** - MCUboot is supported on the SoCs from the following series: + To get started with hardware programmed with pre-configured software, go to the :ref:`nrf_desktop_user_interface` section. - * nRF52 Series - * nRF53 Series - - The MCUboot bootloader can be used in the following scenarios: - - * :ref:`Background DFU `. - In this scenario, the MCUboot either swaps the application images located on the secondary and primary slot before booting a new image (``swap mode``) or boots a new application image directly from the secondary image slot (``direct-xip mode``). - The swap operation significantly increases boot time after a successful image transfer, but external non-volatile memory can be used as the secondary image slot. - - You can use the MCUboot for the background DFU through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. - The MCUboot can also be used for the background DFU over Simple Management Protocol (SMP). - The SMP can be used to transfer the new firmware image in the background, for example, from an Android device. - In that case, either the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr` is used to handle the image transfer. - The :ref:`nrf_desktop_ble_smp` relies on a generic module implemented in the Common Application Framework (CAF). - The :ref:`nrf_desktop_dfu_mcumgr` uses an application-specific implementation that allows to synchronize a secondary image slot access with the :ref:`nrf_desktop_dfu` using the :ref:`nrf_desktop_dfu_lock`. - - * :ref:`USB serial recovery `. - In this scenario, the MCUboot bootloader supports the USB serial recovery. - The USB serial recovery can be used for memory-limited devices that support the USB connection. - In this mode, unlike in the background DFU mode, the DFU image transfer is handled by the bootloader. - The application is not running and it can be overwritten. - Because of that, only one application slot may be used. - - For more information about the MCUboot, see the :ref:`MCUboot ` documentation. - -.. note:: - The nRF Desktop application can use either B0 or MCUboot. - The MCUboot is not used as the second stage bootloader. - -.. important:: - Make sure that you use your own private key for the release version of the devices. - Do not use the debug key for production. - -If your configuration enables the bootloader, make sure to define a static non-volatile memory layout in the Partition Manager. -See :ref:`nrf_desktop_memory_layout` for details. - -Configuring the B0 bootloader ------------------------------ - -To enable the B0 bootloader, select the :kconfig:option:`CONFIG_SECURE_BOOT` Kconfig option in the application configuration. - -The B0 bootloader additionally requires enabling the following options in the application configuration: - -* :kconfig:option:`CONFIG_SB_SIGNING_KEY_FILE` - Required for providing the signature used for image signing and verification. -* :kconfig:option:`CONFIG_FW_INFO` - Required for the application versioning information. -* :kconfig:option:`CONFIG_FW_INFO_FIRMWARE_VERSION` - Enable this option to set the version of the application after you enabled :kconfig:option:`CONFIG_FW_INFO`. - The nRF Desktop application with the B0 bootloader configuration builds two application images: one for the S0 slot and the other for the S1 slot. - To generate the DFU package, you need to update this configuration only in the main application image as the ``s1_image`` child image mirrors it. - You can do that by rebuilding the application from scratch or by changing the configuration of the main image through menuconfig. -* :kconfig:option:`CONFIG_BUILD_S1_VARIANT` - Required for the build system to be able to construct the application binaries for both application's slots in non-volatile memory. - -.. _nrf_desktop_configuring_mcuboot_bootloader: - -Configuring the MCUboot bootloader ----------------------------------- - -To enable the MCUboot bootloader, select the :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` Kconfig option in the application configuration. - -The MCUboot private key path (:kconfig:option:`CONFIG_BOOT_SIGNATURE_KEY_FILE`) must be set only in the MCUboot bootloader configuration file. -The key is used both by the build system (to sign the application update images) and by the bootloader (to verify the application signature using public key derived from the selected private key). - -The MCUboot bootloader configuration depends on the selected way of performing image upgrade. -For detailed information about the available MCUboot bootloader modes, see the following sections. - -Swap mode -~~~~~~~~~ - -In the swap mode, the MCUboot bootloader moves the image to the primary slot before booting it. -The swap mode is the image upgrade mode used by default for the :ref:`background DFU `. - -If the swap mode is used, the application must request firmware upgrade and confirm the running image. -For this purpose, make sure to enable :kconfig:option:`CONFIG_IMG_MANAGER` and :kconfig:option:`CONFIG_MCUBOOT_IMG_MANAGER` Kconfig options in the application configuration. -These options allow the :ref:`nrf_desktop_dfu`, :ref:`nrf_desktop_ble_smp`, and :ref:`nrf_desktop_dfu_mcumgr` to manage the DFU image. - -.. note:: - When the MCUboot bootloader is in the swap mode, it can use a secondary image slot located on the external non-volatile memory. - For details on using external non-volatile memory for the secondary image slot, see the :ref:`nrf_desktop_pm_external_flash` section. - -Direct-xip mode -~~~~~~~~~~~~~~~ - -The direct-xip mode is used for the :ref:`background DFU `. -In this mode, the MCUboot bootloader boots an image directly from a given slot, so the swap operation is not needed. -To set the MCUboot mode of operations to the direct-xip mode, make sure to enable the :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option in the application configuration. -This option automatically enables :kconfig:option:`CONFIG_BOOT_BUILD_DIRECT_XIP_VARIANT` to build application update images for both slots. - -Enable the ``CONFIG_BOOT_DIRECT_XIP`` Kconfig option in the bootloader configuration to make the MCUboot run the image directly from both image slots. -The nRF Desktop's bootloader configurations do not enable the revert mechanism (``CONFIG_BOOT_DIRECT_XIP_REVERT``). -When the direct-xip mode is enabled (the :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option is set in the application configuration), the application modules that control the DFU transport do not request firmware upgrades and do not confirm the running image. -In that scenario, the MCUboot bootloader simply boots the image with the higher image version. - -By default, the MCUboot bootloader ignores the build number while comparing image versions. -Enable the ``CONFIG_BOOT_VERSION_CMP_USE_BUILD_NUMBER`` Kconfig option in the bootloader configuration to use the build number while comparing image versions. -To apply the same option for the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr`, enable the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_VERSION_CMP_USE_BUILD_NUMBER` Kconfig option in the application configuration. - -It is recommended to also enable the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT` Kconfig option in the application configuration to make sure that MCUmgr rejects application image updates with invalid start address. -This prevents uploading an update image build for improper slot through the MCUmgr's Simple Management Protocol (SMP). - -Serial recovery mode -~~~~~~~~~~~~~~~~~~~~ - -In the :ref:`USB serial recovery ` mode, the MCUboot bootloader uses a built-in foreground DFU transport over serial interface through USB. -The application is not involved in the foreground DFU transport, therefore it can be directly overwritten by the bootloader. -Because of that, the configuration with the serial recovery mode requires only a single application slot. - -Enable the USB serial recovery DFU using the following configuration options: - -* ``CONFIG_MCUBOOT_SERIAL`` - This option enables the serial recovery DFU. -* ``CONFIG_BOOT_SERIAL_CDC_ACM`` - This option enables the serial interface through USB. - - .. note:: - Make sure to enable and properly configure the USB subsystem in the bootloader configuration. - See :ref:`usb_api` for more information. - -If the predefined button is pressed during the boot, the MCUboot bootloader enters the serial recovery mode instead of booting the application. -The GPIO pin used to trigger the serial recovery mode is configured using Devicetree Specification (DTS). -The pin is configured with the ``mcuboot-button0`` alias. -The ``mcuboot-led0`` alias can be used to define the LED activated in the serial recovery mode. -The ``CONFIG_MCUBOOT_INDICATION_LED`` Kconfig option must be selected to enable the LED. -By default, both the GPIO pin and the LED are defined in the board's DTS file. -See :file:`boards/arm/nrf52833dongle_nrf52833/nrf52833dongle_nrf52833.dts` for an example of board's DTS file used by the nRF Desktop application. - -For an example of bootloader Kconfig configuration file defined by the application, see the MCUboot bootloader debug configuration defined for nRF52833 dongle (:file:`applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf`). - -.. note:: - The nRF Desktop devices use either the serial recovery DFU with a single application slot or the background DFU. - Both mentioned firmware upgrade methods are not used simultaneously by any of the configurations. - For example, the ``nrf52840dk_nrf52840`` board in ``prj_mcuboot_smp.conf`` uses only the background DFU and does not enable the serial recovery feature. - -.. _nrf_desktop_bootloader_background_dfu: - -Background Device Firmware Upgrade -================================== - -The nRF Desktop application uses the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu` for the background DFU process. -From the application perspective, the update image transfer during the background DFU process is very similar for all supported configurations: - -* MCUboot -* Secure Bootloader (B0) - -The firmware update process has three stages, discussed below. -At the end of these three stages, the nRF Desktop application will be rebooted with the new firmware package installed. - -.. note:: - The background firmware upgrade can also be performed over the Simple Management Protocol (SMP). - For more details about the DFU procedure over SMP, read the documentation of the following modules: - - * :ref:`nrf_desktop_ble_smp` (supported only with MCUboot bootloader) - * :ref:`nrf_desktop_dfu_mcumgr` (supported only with MCUboot bootloader) - The module uses the :ref:`nrf_desktop_dfu_lock` to synchronize non-volatile memory access with other DFU methods. - Therefore, this module should be used for configurations that enable multiple DFU transports (for example, if a configuration also enables :ref:`nrf_desktop_dfu`). - -Update image generation ------------------------ - -The update image is generated in the build directory when building the firmware regardless of the chosen DFU configuration. - -MCUboot and B0 bootloaders -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The :file:`zephyr/dfu_application.zip` file is used by both B0 and MCUboot bootloader for the background DFU through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. -The package contains firmware images along with additional metadata. -If the used bootloader boots the application directly from either slot 0 or slot 1, the host script transfers the update image that can be run from the unused slot. -Otherwise, the image is always uploaded to the slot 1 and then moved to slot 0 by the bootloader before boot. - -.. note:: - Make sure to properly configure the bootloader to ensure that the build system generates the :file:`zephyr/dfu_application.zip` archive containing all of the required update images. - -Update image transfer ---------------------- - -The update image is transmitted in the background through the :ref:`nrf_desktop_config_channel`. -The configuration channel data is transmitted either through USB or over Bluetooth, using HID feature reports. -This allows the device to be used normally during the whole process (that is, the device does not need to enter any special state in which it becomes non-responsive to the user). - -Depending on the side on which the process is handled: - -* On the application side, the process is handled by :ref:`nrf_desktop_dfu`. - See the module documentation for how to enable and configure it. -* On the host side, the process is handled by the :ref:`nrf_desktop_config_channel_script`. - See the tool documentation for more information about how to execute the background DFU process on the host. - -.. _nrf_desktop_image_transfer_over_smp: - -Image transfer over SMP -~~~~~~~~~~~~~~~~~~~~~~~ - -The update image can also be transferred in the background through one of the following modules: - -* :ref:`nrf_desktop_ble_smp` (supported only with MCUboot bootloader) -* :ref:`nrf_desktop_dfu_mcumgr` (supported only with MCUboot bootloader) - The module uses the :ref:`nrf_desktop_dfu_lock` to synchronize non-volatile memory access with other DFU methods. - Therefore, this module should be used for configurations that enable multiple DFU transports (for example, if a configuration also enables :ref:`nrf_desktop_dfu`). - -The `nRF Connect Device Manager`_ application transfers image update files over the Simple Management Protocol (SMP). - -To perform DFU using the `nRF Connect Device Manager`_ mobile app, complete the following steps: - -.. include:: /device_guides/working_with_nrf/nrf52/developing.rst - :start-after: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_start - :end-before: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_end - -.. include:: /device_guides/working_with_nrf/nrf52/developing.rst - :start-after: fota_upgrades_over_ble_mcuboot_direct_xip_nrfcdm_note_start - :end-before: fota_upgrades_over_ble_mcuboot_direct_xip_nrfcdm_note_end - -.. note:: - If the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT` Kconfig option is enabled in the application configuration, the device rejects update image upload for the invalid slot. - It is recommended to enable the option if the application uses MCUboot in the direct-xip mode. - -Update image verification and application image update ------------------------------------------------------- - -Once the update image transfer is completed, the background DFU process will continue after the device reboot. -If :ref:`nrf_desktop_config_channel_script` is used, the reboot is triggered by the script right after the image transfer completes. - -The implementation details of the reboot mechanism for the chosen DFU configuration are described in the following subsections. - -MCUboot and B0 bootloaders -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For these configuration variants, the :c:func:`sys_reboot` function is called to reboot the device. -After the reboot, the bootloader locates the update image on the update partition of the device. -The image verification process ensures the integrity of the image and checks if its signature is valid. -If verification is successful, the bootloader boots the new version of the application. -Otherwise, the old version is used. - -.. _nrf_desktop_bootloader_serial_dfu: - -Serial recovery DFU -=================== - -The serial recovery DFU is a feature of MCUboot and it needs to be enabled in the bootloader's configuration. -For the configuration details, see the :ref:`nrf_desktop_configuring_mcuboot_bootloader` section. - -To start the serial recovery DFU, the device should boot into recovery mode, in which the bootloader will be waiting for a new image upload to start. -In the serial recovery DFU mode, the new image is transferred through an USB CDC ACM class instance. -The bootloader overwrites the existing application located on the primary slot with the new application image. -If the transfer is interrupted, the device will not be able to boot the incomplete application, and the image upload must be performed again. - -Once the device enters the serial recovery mode, you can use the :ref:`mcumgr ` to: - -* Query information about the present image. -* Upload the new image. - The :ref:`mcumgr ` uses the :file:`zephyr/app_update.bin` update image file. - It is generated by the build system when building the firmware. - -For example, the following line will start the upload of the new image to the device: - -.. code-block:: console - - mcumgr -t 60 --conntype serial --connstring=/dev/ttyACM0 image upload build-nrf52833dongle_nrf52833/zephyr/app_update.bin - -The command assumes that ``/dev/ttyACM0`` serial device is used by the MCUboot bootloader for the serial recovery. - -fwupd support -============= - -fwupd is an open-source project providing tools and daemon for managing the installation of firmware updates on Linux-based systems. -Together with the `LVFS (Linux Vendor Firmware Service) `_, it provides a solution for vendors to easily distribute firmware for compatible devices. - -The fwupd tools can communicate with the devices running the nRF Desktop application with the :ref:`nrf_desktop_bootloader_background_dfu` feature enabled. - -Nordic HID plugin ------------------ - -The fwupd project allows communication with multiple types of devices through various communication protocols. -The communication protocols are implemented using plugins. -The plugin associated with the DFU protocol realized through the :ref:`nrf_desktop_config_channel` is branded as ``nordic_hid``. - -Adding a new device -------------------- - -The device specifies which protocol is used for the communication by adding the specific device information to the plugin metadata. -For the ``nordic_hid`` plugin, this file is located at `nordic-hid.quirk`_. -The following example shows the information passed to the plugin metadata: - -.. code-block:: console - - [HIDRAW\VEN_1915&DEV_52DE] - Plugin = nordic_hid - GType = FuNordicHidCfgChannel - NordicHidBootloader = B0 - -In this console snippet: - -* ``[HIDRAW\VEN_1915&DEV_52DE]`` - This line describes the device instance ID provided by the OS, which identifies the device. -* ``Plugin = nordic_hid`` and ``GType = FuNordicHidCfgChannel`` - These lines set the plugin that the device uses. -* ``NordicHidBootloader`` - This optional line selects the bootloader that the device is running. - If the device does not have the information about the underlying bootloader, the ``NordicHidBootloader`` option is used to select a proper bootloader type. - If there is no information about the bootloader, both in metadata and from the device, the update procedure will fail. - The possible values are either ``B0``, ``MCUBOOT`` or ``MCUBOOT+XIP``. - -.. note:: - As the ``nordic_hid`` plugin communicates with the device using the Configuration channel, the device update is not allowed through the Serial recovery DFU. - -To add a new device, a pull request must be opened to the `fwupd`_ repository with a new entry to the :file:`nordic-hid.quirk` file. - -LVFS and update image preparation ---------------------------------- - -The `LVFS (Linux Vendor Firmware Service) `_ hosts firmware images that can be downloaded by Linux machines and used by the fwupd tool for the firmware update of compatible devices. -A vendor account is needed to upload a new firmware archive to the site. -Information on how to apply for an account is found at the `LVFS Getting an account`_ website. - -The nRF Desktop application DFU image is delivered as a zip package, containing a manifest and one or more binary files used for the update. -To prepare the image file compatible with the LVFS, the CAB file needs to be prepared. -The CAB package must contain the DFU package generated by the |NCS|, that is :file:`dfu_application.zip`, plus metadata file with information used by the LVFS. -For more information, see the `LVFS metadata`_ site. - -When the CAB archive has been built, it can be uploaded to the LVFS where the CAB archive is verified and signed. -For more information about creating CAB files, signing, and uploading the update package, see the `LVFS Uploading Firmware`_ site. - -Upgrading firmware using fwupd ------------------------------- - -Once the update image was uploaded onto the LVFS, the firmware update procedure can be tested on end machines. - -Complete the following steps: - -1. Make sure that the host machine to which the updatable device running the nRF Desktop application is connected has the fwupd tool installed. -#. Fetch the information about available update images from the LVFS by using the following commands: - - .. code-block:: console - - fwupdmgr refresh - fwupdmgr get-updates - - In this console snippet: - - * ``fwupdmgr refresh`` - This command downloads the latest metadata from the LVFS. - * ``fwupdmgr get-updates`` - This command displays the updates available for the devices on the host system. - -#. Test the update image on a limited number of devices before it goes public. - For more information about limiting the visibility of updated images uploaded to the LVFS, see the `LVFS testing`_ site. -#. Run the following command to update the devices: - - .. code-block:: console - - fwupdmgr update - -When connecting to the device, the application verifies the bootloader type. -This is done to ensure a compatible firmware is uploaded to the nRF Desktop device, that is software that can support multiple bootloaders. -The device is queried for information about bootloader using the :ref:`nrf_desktop_config_channel`. -If the device does not provide information about the bootloader type, such information can optionally be provided inside the :file:`nordic-hid.quirk` file (see the ``NordicHidBootloader`` option under `Adding a new device`_). - -fwupd can fail the image update in the following cases: - -* When the bootloader information stored in an updated image does not match the type reported by the device. -* When there is no information about the bootloader used on the device. - -For more information about building the fwupd tool locally, see the `LVFS building fwupd`_ site. - -Dependencies -************ - -This application uses the following |NCS| libraries and drivers: - -* :ref:`lib_caf` -* :ref:`app_event_manager` -* :ref:`nrf_profiler` -* :ref:`hids_readme` -* :ref:`hogp_readme` -* :ref:`nrf_bt_scan_readme` -* :ref:`gatt_dm_readme` -* :file:`drivers/sensor/paw3212` -* :file:`drivers/sensor/pmw3360` - -.. _nrf_desktop_app_internal_modules: - -Application internal modules -**************************** - -The nRF Desktop application uses its own set of internal modules. -See `Module and component overview`_ for more information. -More information about each application module and its configuration details is available on the subpages. - -Each module documentation page has a table that shows the relations between module events. -`Module event tables`_ for some modules include extensive lists of source and sink modules. -These are valid for events that have many listeners or sources, and are gathered on the :ref:`nrf_desktop_event_rel_modules` subpage. +See the subpages for detailed documentation on the application and its modules: .. toctree:: :maxdepth: 1 :caption: Subpages: - doc/main.rst - doc/battery_charger.rst - doc/battery_meas.rst - doc/ble_adv.rst - doc/ble_bond.rst - doc/ble_conn_params.rst - doc/ble_discovery.rst - doc/ble_latency.rst - doc/ble_passkey.rst - doc/ble_qos.rst - doc/ble_scan.rst - doc/ble_state_pm.rst - doc/ble_state.rst - doc/board.rst - doc/buttons.rst - doc/buttons_sim.rst - doc/click_detector.rst - doc/config_channel.rst - doc/cpu_meas.rst - doc/dev_descr.rst - doc/dfu.rst - doc/dfu_mcumgr.rst - doc/dfu_lock.rst - doc/factory_reset.rst - doc/failsafe.rst - doc/fast_pair_app.rst - doc/fn_keys.rst - doc/bas.rst - doc/hid_forward.rst - doc/hid_state.rst - doc/hid_state_pm.rst - doc/hids.rst - doc/info.rst - doc/led_state.rst - doc/led_stream.rst - doc/leds.rst - doc/motion.rst - doc/passkey.rst - doc/power_manager.rst - doc/nrf_profiler_sync.rst - doc/qos.rst - doc/selector.rst - doc/smp.rst - doc/settings_loader.rst - doc/swift_pair_app.rst - doc/usb_state_pm.rst - doc/usb_state.rst - doc/watchdog.rst - doc/wheel.rst - doc/constlat.rst - doc/hfclk_lock.rst - doc/event_rel_modules.rst - -.. _config_desktop_app_options: - -Application configuration options -********************************* - -Following are the application specific configuration options that can be configured for the nRF desktop and the internal modules: - -.. options-from-kconfig:: - :show-type: - -API documentation -***************** - -Following are the API elements used by the application. - -HID reports -=========== - -| Header file: :file:`applications/nrf_desktop/configuration/common/hid_report_desc.h` -| Source file: :file:`applications/nrf_desktop/configuration/common/hid_report_desc.c` - -.. doxygengroup:: nrf_desktop_hid_reports - :project: nrf - :members: - -LED states -========== - -| Header file: :file:`applications/nrf_desktop/configuration/common/led_state.h` -| Source file: :file:`applications/nrf_desktop/src/modules/led_state.c` - -.. doxygengroup:: nrf_desktop_led_state - :project: nrf - :members: - -USB events -========== - -| Header file: :file:`applications/nrf_desktop/src/events/usb_event.h` -| Source file: :file:`applications/nrf_desktop/src/modules/usb_state.c` - -.. doxygengroup:: nrf_desktop_usb_event - :project: nrf - :members: + description + application_kconfig + board_configuration + nRF21540ek_support + memory_layout + bluetooth + bootloader_dfu + fwupd + integration + modules + configuration_options + api diff --git a/applications/nrf_desktop/api.rst b/applications/nrf_desktop/api.rst new file mode 100644 index 00000000000..3cd0f645b6d --- /dev/null +++ b/applications/nrf_desktop/api.rst @@ -0,0 +1,40 @@ +.. _nrf_desktop_api: + +nRF Desktop: API documentation +############################## + +.. contents:: + :local: + :depth: 2 + +Following are the API elements used by the application. + +HID reports +*********** + +| Header file: :file:`applications/nrf_desktop/configuration/common/hid_report_desc.h` +| Source file: :file:`applications/nrf_desktop/configuration/common/hid_report_desc.c` + +.. doxygengroup:: nrf_desktop_hid_reports + :project: nrf + :members: + +LED states +********** + +| Header file: :file:`applications/nrf_desktop/configuration/common/led_state.h` +| Source file: :file:`applications/nrf_desktop/src/modules/led_state.c` + +.. doxygengroup:: nrf_desktop_led_state + :project: nrf + :members: + +USB events +********** + +| Header file: :file:`applications/nrf_desktop/src/events/usb_event.h` +| Source file: :file:`applications/nrf_desktop/src/modules/usb_state.c` + +.. doxygengroup:: nrf_desktop_usb_event + :project: nrf + :members: diff --git a/applications/nrf_desktop/application_kconfig.rst b/applications/nrf_desktop/application_kconfig.rst new file mode 100644 index 00000000000..b0babf5aa63 --- /dev/null +++ b/applications/nrf_desktop/application_kconfig.rst @@ -0,0 +1,127 @@ +.. _nrf_desktop_application_Kconfig: + +nRF Desktop: Application-specific Kconfig options +################################################# + +.. contents:: + :local: + :depth: 2 + +The nRF Desktop introduces Kconfig options that you can use to simplify an application configuration. +You can use these options to select a device role and to automatically apply a default configuration suitable for the selected role. + +.. note:: + Part of the default configuration is applied by modifying the default values of Kconfig options. + Changing configuration in menuconfig does not automatically adjust user-configurable values to the new defaults. + So, you must update those values manually. + For more information, see the Stuck symbols in menuconfig and guiconfig section on the :ref:`kconfig_tips_and_tricks` in the Zephyr documentation. + + The default Kconfig option values are automatically updated if configuration changes are applied directly in the configuration files. + +.. _nrf_desktop_hid_configuration: + +HID configuration +***************** + +The nRF Desktop application introduces application-specific configuration options related to HID device configuration. +These options are defined in :file:`Kconfig.hid`. + +The options define the nRF Desktop device role. +The device role can be either a HID dongle (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) or a HID peripheral (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `). +The HID peripheral role can also specify a peripheral type: + +* HID mouse (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE `) +* HID keyboard (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_KEYBOARD `) +* other HID device (:ref:`CONFIG_DESKTOP_PERIPHERAL_TYPE_OTHER `) + +Each role automatically implies the nRF Desktop modules needed for the role. +For example, :ref:`nrf_desktop_hid_state` is automatically enabled for the HID peripheral role. + +By default, the nRF Desktop devices use a predefined format of HID reports. +The common HID report map is defined in the :file:`configuration/common/hid_report_desc.c` file. +The selected role implies a set of related HID reports. +For example, HID mouse automatically enables support for HID mouse report. +If you select ``other HID device`` peripheral type, you need to explicitly define the set of HID reports in the configuration. + +Apart from this, you can specify the supported HID boot protocol interface as one of the following: + +* mouse (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE `) +* keyboard (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD `) +* none (:ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_DISABLED `) + +.. _nrf_desktop_hid_device_identifiers: + +HID device identifiers +====================== + +The nRF Desktop application defines the following common device identifiers: + +* Manufacturer (:ref:`CONFIG_DESKTOP_DEVICE_MANUFACTURER `) +* Vendor ID (:ref:`CONFIG_DESKTOP_DEVICE_VID `) +* Product name (:ref:`CONFIG_DESKTOP_DEVICE_PRODUCT `) +* Product ID (:ref:`CONFIG_DESKTOP_DEVICE_PID `) + +These Kconfig options determine the default values of device identifiers used for: + +* :ref:`nrf_desktop_usb_state_identifiers` +* BLE GATT Device Information Service (:kconfig:option:`CONFIG_BT_DIS`) that is required for :ref:`nrf_desktop_bluetooth_guide_peripheral` + +.. note:: + Apart from the mentioned common device identifiers, the nRF Desktop application defines an application-specific string representing device generation (:ref:`CONFIG_DESKTOP_DEVICE_GENERATION `). + The generation allows to distinguish configurations that use the same board and bootloader, but are not interoperable. + The value can be read through the :ref:`nrf_desktop_config_channel`. + +Debug configuration +******************* + +The nRF Desktop application introduces application-specific configuration options related to the ``debug`` configuration. +These options are defined in the :file:`Kconfig.debug` file. + +The :ref:`CONFIG_DESKTOP_LOG ` Kconfig option enables support for logging in the nRF Desktop application. +This option overlays Kconfig option defaults from the Logging subsystem to align them with the nRF Desktop requirements. +The nRF Desktop configuration uses SEGGER J-Link RTT as the Logging subsystem backend. + +The :ref:`CONFIG_DESKTOP_SHELL ` Kconfig option enables support for CLI in the nRF Desktop application. +This option overlays Kconfig option defaults from the Shell subsystem to align them with the nRF Desktop requirements. +The nRF Desktop configuration uses SEGGER J-Link RTT as the Shell subsystem backend. +If both shell and logging are enabled, logger uses shell as the logging backend. + +See the :file:`Kconfig.debug` file content for details. + +Default common configuration +**************************** + +The nRF Desktop application aligns the configuration with the nRF Desktop use case by overlaying Kconfig defaults and selecting or implying the required Kconfig options. +Among others, the Kconfig :ref:`app_event_manager` and :ref:`lib_caf` options are selected to ensure that they are enabled. +The :ref:`CONFIG_DESKTOP_SETTINGS_LOADER ` and :ref:`CONFIG_DESKTOP_POWER_MANAGER ` are implied to enable the :ref:`nrf_desktop_settings_loader` and :ref:`nrf_desktop_power_manager` modules, respectively. +See the :file:`Kconfig.defaults` file for details related to the default common configuration. + +.. _nrf_desktop_bluetooth_configuration: + +Bluetooth configuration +*********************** + +The nRF Desktop application introduces application-specific configuration options related to Bluetooth connectivity configuration. +These options are defined in :file:`Kconfig.ble` file. + +The :ref:`CONFIG_DESKTOP_BT ` Kconfig option enables support for Bluetooth connectivity in the nRF Desktop application. +The option is enabled by default. + +The nRF Desktop Bluetooth peripheral configuration (:ref:`CONFIG_DESKTOP_BT_PERIPHERAL `) is automatically enabled for the nRF Desktop HID peripheral role (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `). +The nRF Desktop Bluetooth central configuration (:ref:`CONFIG_DESKTOP_BT_CENTRAL `) is automatically enabled for the nRF Desktop HID dongle role (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) + +The nRF Desktop Bluetooth configuration options perform the following: + +* Imply Bluetooth-related application modules that are required for the selected device role. +* Select required functionalities in Zephyr's Bluetooth stack. +* Overlay Bluetooth Kconfig option defaults to align them with the nRF Desktop use case. + +See :file:`Kconfig.ble` file content for details. +See the :ref:`nrf_desktop_bluetooth_guide` for more information about Bluetooth support in nRF Desktop application. + +CAF configuration +****************** + +The nRF Desktop application overlays the defaults of the :ref:`lib_caf` related Kconfig options to align them with the nRF Desktop use case. +The files that apply the overlays are located in the :file:`src/modules` directory and are named :file:`Kconfig.caf_module_name.default`. +For example, the Kconfig defaults of :ref:`caf_settings_loader` are overlayed in the :file:`src/modules/Kconfig.caf_settings_loader.default`. diff --git a/applications/nrf_desktop/bluetooth.rst b/applications/nrf_desktop/bluetooth.rst new file mode 100644 index 00000000000..e636496329b --- /dev/null +++ b/applications/nrf_desktop/bluetooth.rst @@ -0,0 +1,225 @@ +.. _nrf_desktop_bluetooth_guide: + +nRF Desktop: Bluetooth +###################### + +.. contents:: + :local: + :depth: 2 + +The nRF Desktop devices use :ref:`Zephyr's Bluetooth API ` to handle the Bluetooth LE connections. + +This API is used only by the application modules that handle such connections. +The information about peer and connection state is propagated to other application modules using :ref:`app_event_manager` events. + +The :ref:`CONFIG_DESKTOP_BT ` Kconfig option enables support for Bluetooth connectivity in the nRF Desktop. +Specific Bluetooth configurations and application modules are selected or implied according to the HID device role. +Apart from that, the defaults of Bluetooth-related Kconfigs are aligned with the nRF Desktop use case. + +The nRF Desktop devices come in the following roles: + +* HID peripheral (:ref:`CONFIG_DESKTOP_ROLE_HID_PERIPHERAL `) that works as a Bluetooth Peripheral (:ref:`CONFIG_DESKTOP_BT_PERIPHERAL `) + + * Support only the Bluetooth Peripheral role (:kconfig:option:`CONFIG_BT_PERIPHERAL`). + * Handle only one Bluetooth LE connection at a time. + * Use more than one Bluetooth local identity. + +* HID dongle (:ref:`CONFIG_DESKTOP_ROLE_HID_DONGLE `) that works as a Bluetooth Central (:ref:`CONFIG_DESKTOP_BT_CENTRAL `) + + * Support only the Bluetooth Central role (:kconfig:option:`CONFIG_BT_CENTRAL`). + * Handle multiple Bluetooth LE connections simultaneously. + * Use only one Bluetooth local identity (the default one). + +Both central and peripheral devices have dedicated configuration options and use dedicated modules. + +The nRF Desktop peripheral configurations that enable `Fast Pair`_ support use a slightly different Bluetooth configuration. +This is needed to improve the user experience. +See :ref:`nrf_desktop_bluetooth_guide_fast_pair` for more details. + +.. note:: + An nRF Desktop device cannot support both central and peripheral roles. + +Common configuration and application modules +******************************************** + +Some Bluetooth-related :ref:`configuration options ` (including :ref:`nrf_desktop_bluetooth_guide_configuration_ll` in a separate section) and :ref:`application modules ` are common for every nRF Desktop device. + +.. _nrf_desktop_bluetooth_guide_configuration: + +Configuration options +===================== + +This section describes the most important Bluetooth Kconfig options common for all nRF Desktop devices. +For detailed information about every option, see the Kconfig help. + +* :kconfig:option:`CONFIG_BT_MAX_PAIRED` + + * nRF Desktop central: The maximum number of paired devices is greater than or equal to the maximum number of simultaneously connected peers. + The :kconfig:option:`CONFIG_BT_MAX_PAIRED` is by default set to :ref:`CONFIG_DESKTOP_HID_DONGLE_BOND_COUNT `. + * nRF Desktop peripheral: The maximum number of paired devices is equal to the number of peers plus one, where the one additional paired device slot is used for erase advertising. + +* :kconfig:option:`CONFIG_BT_ID_MAX` + + * nRF Desktop central: The device uses only one Bluetooth local identity, that is the default one. + * nRF Desktop peripheral: The number of Bluetooth local identities must be equal to the number of peers plus two. + + * One additional local identity is used for erase advertising. + * The other additional local identity is the default local identity, which is unused, because it cannot be reset after removing the bond. + Without the identity reset, the previously bonded central could still try to reconnect after being removed from Bluetooth bonds on the peripheral side. + +* :kconfig:option:`CONFIG_BT_MAX_CONN` + + * nRF Desktop central: This option is set to the maximum number of simultaneously connected devices. + The :kconfig:option:`CONFIG_BT_MAX_CONN` is by default set to :ref:`CONFIG_DESKTOP_HID_DONGLE_CONN_COUNT `. + * nRF Desktop peripheral: The default value (one) is used. + +.. note:: + After changing the number of Bluetooth peers for the nRF Desktop peripheral device, update the LED effects used to represent the Bluetooth connection state. + For details, see :ref:`nrf_desktop_led_state`. + +.. _nrf_desktop_bluetooth_guide_configuration_ll: + +Link Layer configuration options +================================ + +The nRF Desktop devices use one of the following Link Layers: + +* :kconfig:option:`CONFIG_BT_LL_SW_SPLIT` + This Link Layer does not support the Low Latency Packet Mode (LLPM) and has a lower memory usage, so it can be used by memory-limited devices. + +* :kconfig:option:`CONFIG_BT_LL_SOFTDEVICE` + This Link Layer does support the Low Latency Packet Mode (LLPM). + If you opt for this Link Layer and enable the :kconfig:option:`CONFIG_BT_CTLR_SDC_LLPM`, the :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is also enabled by default and can be configured further: + + * When :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is enabled, set the value for :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``3000``. + + This is required by the nRF Desktop central and helps avoid scheduling conflicts with the Bluetooth Link Layer. + Such conflicts could lead to a drop in HID input report rate or a disconnection. + Because of this, if the nRF Desktop central supports LLPM and more than one simultaneous Bluetooth connection, it also uses 10 ms connection interval instead of 7.5 ms. + Setting the value of :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``3000`` also enables the nRF Desktop central to exchange data with up to three standard Bluetooth LE peripherals during every connection interval (every 10 ms). + + * When :kconfig:option:`CONFIG_CAF_BLE_USE_LLPM` is disabled, the device will use only standard Bluetooth LE connection parameters with the lowest available connection interval of 7.5 ms. + + If the LLPM is disabled and more than two simultaneous Bluetooth connections are supported (:kconfig:option:`CONFIG_BT_MAX_CONN`), you can set the value for :kconfig:option:`CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT` to ``2500``. + With this value, the nRF Desktop central can exchange the data with up to three Bluetooth LE peripherals during every 7.5-ms connection interval. + Using the value of ``3000`` for more than two simultaneous Bluetooth LE connections will result in a lower HID input report rate. + +.. _nrf_desktop_bluetooth_guide_modules: + +Application modules +=================== + +Every nRF Desktop device that enables Bluetooth must handle connections and manage bonds. +These features are implemented by the following modules: + +* :ref:`nrf_desktop_ble_state` - Enables Bluetooth and LLPM (if supported), and handles Zephyr connection callbacks. +* :ref:`nrf_desktop_ble_bond` - Manages Bluetooth bonds and local identities. + +You need to enable all these modules to enable both features. +For information about how to enable the modules, see their respective documentation pages. + +Optionally, you can also enable the following module: + +* :ref:`nrf_desktop_ble_qos` - Helps achieve better connection quality and higher report rate. + The module can be used only with the SoftDevice Link Layer. + +.. note:: + The nRF Desktop devices enable the :kconfig:option:`CONFIG_BT_SETTINGS` Kconfig option. + When this option is enabled, the application is responsible for calling the :c:func:`settings_load` function - this is handled by the :ref:`nrf_desktop_settings_loader`. + +.. _nrf_desktop_bluetooth_guide_peripheral: + +Bluetooth Peripheral +******************** + +The nRF Desktop peripheral devices must include additional configuration options and additional application modules to comply with the HID over GATT specification. + +The HID over GATT profile specification requires Bluetooth Peripherals to define the following GATT Services: + +* HID Service - Handled in the :ref:`nrf_desktop_hids`. +* Battery Service - Handled in the :ref:`nrf_desktop_bas`. +* Device Information Service - Implemented in Zephyr and enabled with the :kconfig:option:`CONFIG_BT_DIS` Kconfig option. + The device identifiers are configured according to the common :ref:`nrf_desktop_hid_device_identifiers` by default. + You can configure it using Kconfig options with the ``CONFIG_BT_DIS`` prefix. + +The nRF Desktop peripherals must also define a dedicated GATT Service that is used to provide the following information: + +* Information on whether the device can use the LLPM Bluetooth connection parameters. +* Hardware ID of the peripheral. + +The GATT Service is implemented by the :ref:`nrf_desktop_dev_descr`. + +Apart from the GATT Services, an nRF Desktop peripheral device must enable and configure the following application modules: + +* :ref:`nrf_desktop_ble_adv` - Controls the Bluetooth advertising. +* :ref:`nrf_desktop_ble_latency` - Keeps the connection latency low when the :ref:`nrf_desktop_config_channel` is used or when either the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr` receives an update image. + This is done to ensure quick data transfer. + +Optionally, you can also enable the following module: + +* :ref:`nrf_desktop_qos` - Forwards the Bluetooth LE channel map generated by :ref:`nrf_desktop_ble_qos`. + The Bluetooth LE channel map is forwarded using GATT characteristic. + The Bluetooth Central can apply the channel map to avoid congested RF channels. + This results in better connection quality and a higher report rate. + +.. _nrf_desktop_bluetooth_guide_fast_pair: + +Fast Pair +========= + +The nRF Desktop peripheral can be built with Google `Fast Pair`_ support. +The configurations that enable Fast Pair are set in the :file:`prj_fast_pair.conf` and :file:`prj_release_fast_pair.conf` files. + +.. note:: + The Fast Pair integration in the nRF Desktop is :ref:`experimental `. + The factory reset of the Fast Pair non-volatile data is not yet supported. + + The Fast Pair support in the |NCS| is :ref:`experimental `. + See :ref:`ug_bt_fast_pair` for details. + +These configurations support multiple bonds for each Bluetooth local identity (:kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS` is set to ``3``) and erase advertising (:ref:`CONFIG_DESKTOP_BLE_PEER_ERASE `), but Bluetooth peer selection (:ref:`CONFIG_DESKTOP_BLE_PEER_SELECT `) is disabled. +You can now pair with your other hosts without switching the peripheral back in pairing mode (without triggering the erase advertising). +The nRF Desktop peripheral that integrates Fast Pair behaves as follows: + + * The dongle peer does not use the Fast Pair advertising payload. + * The bond erase operation is enabled for the dongle peer. + This lets you change the bonded Bluetooth Central. + * If the dongle peer (:ref:`CONFIG_DESKTOP_BLE_DONGLE_PEER_ENABLE `) is enabled, the `Swift Pair`_ payload is, by default, included only for the mentioned peer. + In the Fast Pair configurations, the dongle peer is intended to be used for all of the peers that are not Fast Pair Seekers. + * If the used Bluetooth local identity has no bonds, the device advertises in pairing mode, and the Fast Pair discoverable advertising is used. + This allows to pair with the nRF Desktop device using both Fast Pair and normal Bluetooth pairing flows. + This advertising payload is also used during the erase advertising. + * If the used Bluetooth local identity already has a bond, the device is no longer in the pairing mode and the Fast Pair not discoverable advertising is used. + This allows to pair only with the Fast Pair Seekers linked to Google Accounts that are already associated with the nRF Desktop device. + In this mode, the device rejects normal Bluetooth pairing by default (:ref:`CONFIG_DESKTOP_FAST_PAIR_LIMIT_NORMAL_PAIRING ` option is enabled). + The Fast Pair UI indication is hidden after the Provider reaches :kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS` bonded peers on the used local identity. + * The :ref:`nrf_desktop_factory_reset` is enabled by default if the :ref:`nrf_desktop_config_channel` is supported by the device. + The factory reset operation removes both Fast Pair and Bluetooth non-volatile data. + The factory reset operation is triggered using the configuration channel. + +After a successful erase advertising procedure, the peripheral removes all of the bonds of a given Bluetooth local identity. + +Apart from that, the following changes are applied in configurations that support Fast Pair: + +* The static :ref:`partition_manager` configuration is modified to introduce a dedicated non-volatile memory partition used to store the Fast Pair provisioning data. +* Bluetooth privacy feature (:kconfig:option:`CONFIG_BT_PRIVACY`) is enabled. +* The fast and slow advertising intervals defined in the :ref:`nrf_desktop_ble_adv` are aligned with Fast Pair expectations. +* The Bluetooth advertising filter accept list (:kconfig:option:`CONFIG_CAF_BLE_ADV_FILTER_ACCEPT_LIST`) is disabled to allow Fast Pair Seekers other than the bonded one to connect outside of the pairing mode. +* The security failure timeout (:ref:`CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S `) is longer to prevent disconnections during the Fast Pair procedure. +* Passkey authentication (:ref:`CONFIG_DESKTOP_BLE_ENABLE_PASSKEY `) is disabled on the keyboard. + Currently, Fast Pair does not support devices that use a screen or keyboard for Bluetooth authentication. +* TX power correction value (:kconfig:option:`CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL`) is configured to align the TX power included in the advertising data with the Fast Pair expectations. + +See :ref:`ug_bt_fast_pair` for detailed information about Fast Pair support in the |NCS|. + +Bluetooth Central +***************** + +The nRF Desktop central must implement Bluetooth scanning and handle the GATT operations. +The central must also control the Bluetooth connection parameters. +These features are implemented by the following application modules: + +* :ref:`nrf_desktop_ble_scan` - Controls the Bluetooth scanning. +* :ref:`nrf_desktop_ble_conn_params` - Controls the Bluetooth connection parameters and reacts on latency update requests received from the connected peripherals. +* :ref:`nrf_desktop_ble_discovery` - Handles discovering and reading the GATT Characteristics from the connected peripheral. +* :ref:`nrf_desktop_hid_forward` - Subscribes for HID reports from the Bluetooth Peripherals (HID over GATT) and forwards data using application events. diff --git a/applications/nrf_desktop/board_configuration.rst b/applications/nrf_desktop/board_configuration.rst new file mode 100644 index 00000000000..8552b3d9c03 --- /dev/null +++ b/applications/nrf_desktop/board_configuration.rst @@ -0,0 +1,115 @@ +.. _nrf_desktop_board_configuration: + +nRF Desktop: Board configuration +################################ + +.. contents:: + :local: + :depth: 2 + +The nRF Desktop application is modular. +Depending on requested functions, it can provide mouse, keyboard, or dongle functionality. +The selection of modules depends on the chosen role and also on the selected reference design. +For more information about modules available for each configuration, see :ref:`nrf_desktop_architecture`. + +For a board to be supported by the application, you must provide a set of configuration files at :file:`applications/nrf_desktop/configuration/your_board_name`. +The application configuration files define both a set of options with which the nRF Desktop application will be created for your board and the selected :ref:`nrf_desktop_requirements_build_types`. +Include the following files in this directory: + +Mandatory configuration files + * Application configuration file for the :ref:`debug build type ` (:file:`prj.conf`). + * Configuration files for the selected modules. + +Optional configuration files + * Application configuration files for other build types. + * Configuration file for the bootloader. + * Memory layout configuration. + * DTS overlay file. + +See :ref:`porting_guide_adding_board` for information about how to add these files. + +.. _nrf_desktop_board_configuration_files: + +nRF Desktop board configuration files +************************************* + +The nRF Desktop application comes with configuration files for the following reference designs: + +nRF52840 Gaming Mouse (``nrf52840gmouse_nrf52840``) + * The reference design is defined in :file:`nrf/boards/arm/nrf52840gmouse_nrf52840` for the project-specific hardware. + * To achieve gaming-grade performance: + + * The application is configured to act as a gaming mouse, with both Bluetooth LE and USB transports enabled. + * Bluetooth is configured to use Nordic's SoftDevice link layer. + + * The configuration with the B0 bootloader is set as default. + * The board supports ``debug`` (:file:`prj_fast_pair.conf`) and ``release`` (:file:`prj_release_fast_pair.conf`) :ref:`nrf_desktop_bluetooth_guide_fast_pair` configurations. + Both configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and they support the firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. + +nRF52832 Desktop Mouse (``nrf52dmouse_nrf52832``) and nRF52810 Desktop Mouse (``nrf52810dmouse_nrf52810``) + * Both reference designs are meant for the project-specific hardware and are defined in :file:`nrf/boards/arm/nrf52dmouse_nrf52832` and :file:`nrf/boards/arm/nrf52810dmouse_nrf52810`, respectively. + * The application is configured to act as a mouse. + * Only the Bluetooth LE transport is enabled. + Bluetooth uses either Zephyr's software link layer (``nrf52810dmouse_nrf52810``) or Nordic's SoftDevice link layer (``nrf52dmouse_nrf52832``). + * The preconfigured build types for both ``nrf52dmouse_nrf52832`` and ``nrf52810dmouse_nrf52810`` boards are without the bootloader due to memory size limits on the ``nrf52810dmouse_nrf52810`` board. + +Sample mouse, keyboard or dongle (``nrf52840dk_nrf52840``) + * The configuration uses the nRF52840 Development Kit. + * The build types allow to build the application as mouse, keyboard or dongle. + * Inputs are simulated based on the hardware button presses. + * The configuration with the B0 bootloader is set as default. + * The board supports ``debug`` :ref:`nrf_desktop_bluetooth_guide_fast_pair` configuration that acts as a mouse (:file:`prj_fast_pair.conf`). + The configuration uses the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and supports firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. + +Sample dongle (``nrf52833dk_nrf52833``) + * The configuration uses the nRF52833 Development Kit. + * The application is configured to act as a dongle that forwards data from both mouse and keyboard. + * Bluetooth uses Nordic Semiconductor's SoftDevice link layer and is configured to act as a central. + Input data comes from Bluetooth and is retransmitted to USB. + * The configuration with the MCUboot bootloader is set as default. + +Sample dongle (``nrf52833dk_nrf52820``) + * The configuration uses the nRF52820 emulation on the nRF52833 Development Kit. + * The application is configured to act as a dongle that forwards data from both mouse and keyboard. + * Bluetooth uses Zephyr's software link layer and is configured to act as a central. + Input data comes from Bluetooth and is retransmitted to USB. + * |preconfigured_build_types| + +nRF52832 Desktop Keyboard (``nrf52kbd_nrf52832``) + * The reference design used is defined in :file:`nrf/boards/arm/nrf52kbd_nrf52832` for the project-specific hardware. + * The application is configured to act as a keyboard, with the Bluetooth LE transport enabled. + * Bluetooth is configured to use Nordic Semiconductor's SoftDevice link layer. + * The preconfigured build types configure the device without the bootloader in debug mode and with B0 bootloader in release mode due to memory size limits. + * The board supports ``release`` :ref:`nrf_desktop_bluetooth_guide_fast_pair` configuration (:file:`prj_release_fast_pair.conf`). + The configuration uses the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``), and supports firmware updates using the :ref:`nrf_desktop_dfu` and the :ref:`nrf_desktop_dfu_mcumgr`. + +nRF52840 USB Dongle (``nrf52840dongle_nrf52840``) and nRF52833 USB Dongle (``nrf52833dongle_nrf52833``) + * Since the nRF52840 Dongle is generic and defined in Zephyr, project-specific changes are applied in the DTS overlay file. + * The application is configured to act as a dongle that forwards data from both mouse and keyboard. + * Bluetooth uses Nordic Semiconductor's SoftDevice link layer and is configured to act as a central. + Input data comes from Bluetooth and is retransmitted to USB. + * The configuration with the B0 bootloader is set as default for the ``nrf52840dongle_nrf52840`` board and with the MCUboot bootloader is set as default for the ``nrf52833dongle_nrf52833`` board. + +nRF52820 USB Dongle (``nrf52820dongle_nrf52820``) + * The application is configured to act as a dongle that forwards data from both mouse and keyboard. + * Bluetooth uses Zephyr's software link layer and is configured to act as a central. + Input data comes from Bluetooth and is retransmitted to USB. + * |preconfigured_build_types| + +Sample dongle (``nrf5340dk_nrf5340``) + * The application is configured to act as a dongle that forwards data from both mouse and keyboard. + * Bluetooth uses Nordic Semiconductor's SoftDevice link layer without LLPM and is configured to act as a central. + Input data comes from Bluetooth and is retransmitted to USB. + * The configuration with the B0 bootloader is set as default. + +Sample mouse or keyboard (``nrf54l15pdk_nrf54l15_cpuapp``) + * The configuration uses the nRF54L15 Preview Development Kit (PDK). + * The build types allow to build the application as a mouse or a keyboard. + * Inputs are simulated based on the hardware button presses. + On the PDK PCA10156, revision v0.2.1 AB0-ES5, GPIOs assigned to **Button 3** and **Button 4** do not support interrupts. + Because of this, the application cannot use those buttons. + * Only Bluetooth LE transport is enabled. + Bluetooth LE is configured to use Nordic Semiconductor's SoftDevice Link Layer and Low Latency Packet Mode (LLPM). + * In debug configurations, logs are provided through the UART. + For detailed information on working with the nRF54L15 PDK, see the :ref:`ug_nrf54l15_gs` documentation. + * The configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``) and support firmware updates using the :ref:`nrf_desktop_dfu`. diff --git a/applications/nrf_desktop/bootloader_dfu.rst b/applications/nrf_desktop/bootloader_dfu.rst new file mode 100644 index 00000000000..c5b74746b83 --- /dev/null +++ b/applications/nrf_desktop/bootloader_dfu.rst @@ -0,0 +1,296 @@ +.. _nrf_desktop_bootloader: + +nRF Desktop: Bootloader and Device Firmware Update +################################################## + +.. contents:: + :local: + :depth: 2 + +The nRF Desktop application uses the :ref:`bootloaders ` firmware image that allows you to upgrade the used application firmware image using the :ref:`app_dfu` procedure. + +You can use the following Device Firmware Update (DFU) procedures for upgrading the application firmware version: + +* :ref:`nrf_desktop_bootloader_background_dfu` +* :ref:`nrf_desktop_bootloader_serial_dfu` + +Bootloader +********** + +The nRF Desktop application can use one of the following bootloaders: + +**Secure Bootloader** + In this documentation, the Secure Bootloader is referred as *B0*. + B0 is a small, simple, and secure bootloader that allows the application to boot directly from one of the application slots, thus increasing the speed of the direct firmware upgrade (DFU) process. + B0 is supported on the SoCs from the following series: + + * nRF52 Series + * nRF53 Series (supports only application core DFU) + + This bootloader can be used only for the :ref:`background DFU ` through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. + For more information about the B0, see the :ref:`bootloader` page. + +**MCUboot** + MCUboot is supported on the SoCs from the following series: + + * nRF52 Series + * nRF53 Series + + The MCUboot bootloader can be used in the following scenarios: + + * :ref:`Background DFU `. + In this scenario, the MCUboot either swaps the application images located on the secondary and primary slots before booting a new image (``swap mode``) or boots a new application image directly from the secondary image slot (``direct-xip mode``). + The swap operation significantly increases boot time after a successful image transfer, but external non-volatile memory can be used as the secondary image slot. + + You can use the MCUboot for the background DFU through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. + The MCUboot can also be used for the background DFU over the Simple Management Protocol (SMP). + The SMP can be used to transfer the new firmware image in the background, for example, from an Android device. + In that case, either the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr` is used to handle the image transfer. + The :ref:`nrf_desktop_ble_smp` relies on a generic module implemented in the Common Application Framework (CAF). + The :ref:`nrf_desktop_dfu_mcumgr` uses an application-specific implementation that allows to synchronize a secondary image slot access with the :ref:`nrf_desktop_dfu` using the :ref:`nrf_desktop_dfu_lock`. + + * :ref:`USB serial recovery `. + In this scenario, the MCUboot bootloader supports the USB serial recovery. + The USB serial recovery can be used for memory-limited devices that support the USB connection. + In this mode, unlike in the background DFU mode, the DFU image transfer is handled by the bootloader. + The application is not running and it can be overwritten. + Because of that, only one application slot may be used. + + For more information about the MCUboot, see the :ref:`MCUboot ` documentation. + +.. note:: + The nRF Desktop application can use either B0 or MCUboot. + The MCUboot is not used as the second stage bootloader. + +.. important:: + Make sure that you use your own private key for the release version of the devices. + Do not use the debug key for production. + +If your configuration enables the bootloader, make sure to define a static non-volatile memory layout in the Partition Manager. +See :ref:`nrf_desktop_memory_layout` for details. + +Configuring the B0 bootloader +============================= + +To enable the B0 bootloader, select the :kconfig:option:`CONFIG_SECURE_BOOT` Kconfig option in the application configuration. + +The B0 bootloader additionally requires enabling the following options in the application configuration: + +* :kconfig:option:`CONFIG_SB_SIGNING_KEY_FILE` - Required for providing the signature used for image signing and verification. +* :kconfig:option:`CONFIG_FW_INFO` - Required for the application versioning information. +* :kconfig:option:`CONFIG_FW_INFO_FIRMWARE_VERSION` - Enable this option to set the version of the application after you enabled :kconfig:option:`CONFIG_FW_INFO`. + The nRF Desktop application with the B0 bootloader configuration builds two application images: one for the S0 slot and the other for the S1 slot. + To generate the DFU package, you need to update this configuration only in the main application image as the ``s1_image`` child image mirrors it. + You can do that by rebuilding the application from scratch or by changing the configuration of the main image through menuconfig. +* :kconfig:option:`CONFIG_BUILD_S1_VARIANT` - Required for the build system to be able to construct the application binaries for both application's slots in non-volatile memory. + +.. _nrf_desktop_configuring_mcuboot_bootloader: + +Configuring the MCUboot bootloader +================================== + +To enable the MCUboot bootloader, select the :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` Kconfig option in the application configuration. + +The MCUboot private key path (:kconfig:option:`CONFIG_BOOT_SIGNATURE_KEY_FILE`) must be set only in the MCUboot bootloader configuration file. +The key is used both by the build system (to sign the application update images) and by the bootloader (to verify the application signature using public key derived from the selected private key). + +The MCUboot bootloader configuration depends on the selected way of performing image upgrade. +For detailed information about the available MCUboot bootloader modes, see the following sections. + +Swap mode +--------- + +In the swap mode, the MCUboot bootloader moves the image to the primary slot before booting it. +The swap mode is the image upgrade mode used by default for the :ref:`background DFU `. + +If the swap mode is used, the application must request a firmware upgrade and confirm the running image. +For this purpose, make sure to enable the :kconfig:option:`CONFIG_IMG_MANAGER` and :kconfig:option:`CONFIG_MCUBOOT_IMG_MANAGER` Kconfig options in the application configuration. +These options allow the :ref:`nrf_desktop_dfu`, :ref:`nrf_desktop_ble_smp`, and :ref:`nrf_desktop_dfu_mcumgr` to manage the DFU image. + +.. note:: + When the MCUboot bootloader is in the swap mode, it can use a secondary image slot located on the external non-volatile memory. + For details on using external non-volatile memory for the secondary image slot, see the :ref:`nrf_desktop_pm_external_flash` section. + +Direct-xip mode +--------------- + +The direct-xip mode is used for the :ref:`background DFU `. +In this mode, the MCUboot bootloader boots an image directly from a given slot, so the swap operation is not needed. +To set the MCUboot mode of operations to the direct-xip mode, make sure to enable the :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option in the application configuration. +This option automatically enables :kconfig:option:`CONFIG_BOOT_BUILD_DIRECT_XIP_VARIANT` to build application update images for both slots. + +Enable the ``CONFIG_BOOT_DIRECT_XIP`` Kconfig option in the bootloader configuration to make the MCUboot run the image directly from both image slots. +The nRF Desktop's bootloader configurations do not enable the revert mechanism (``CONFIG_BOOT_DIRECT_XIP_REVERT``). +When the direct-xip mode is enabled (the :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option is set in the application configuration), the application modules that control the DFU transport do not request firmware upgrades and do not confirm the running image. +In that scenario, the MCUboot bootloader simply boots the image with the higher image version. + +By default, the MCUboot bootloader ignores the build number while comparing image versions. +Enable the ``CONFIG_BOOT_VERSION_CMP_USE_BUILD_NUMBER`` Kconfig option in the bootloader configuration to use the build number while comparing image versions. +To apply the same option for the :ref:`nrf_desktop_ble_smp` or :ref:`nrf_desktop_dfu_mcumgr`, enable the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_VERSION_CMP_USE_BUILD_NUMBER` Kconfig option in the application configuration. + +It is recommended to also enable the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT` Kconfig option in the application configuration to make sure that MCUmgr rejects application image updates with invalid start address. +This prevents uploading an update image build for improper slot through the MCUmgr's Simple Management Protocol (SMP). + +Serial recovery mode +-------------------- + +In the :ref:`USB serial recovery ` mode, the MCUboot bootloader uses a built-in foreground DFU transport over serial interface through USB. +The application is not involved in the foreground DFU transport, therefore it can be directly overwritten by the bootloader. +Because of that, the configuration with the serial recovery mode requires only a single application slot. + +Enable the USB serial recovery DFU using the following configuration options: + +* ``CONFIG_MCUBOOT_SERIAL`` - This option enables the serial recovery DFU. +* ``CONFIG_BOOT_SERIAL_CDC_ACM`` - This option enables the serial interface through USB. + + .. note:: + Make sure to enable and properly configure the USB subsystem in the bootloader configuration. + See :ref:`usb_api` for more information. + +If you press the predefined button during the boot, the MCUboot bootloader enters the serial recovery mode instead of booting the application. +The GPIO pin used to trigger the serial recovery mode is configured using Devicetree Specification (DTS). +The pin is configured with the ``mcuboot-button0`` alias. +The ``mcuboot-led0`` alias can be used to define the LED activated in the serial recovery mode. +You must select the ``CONFIG_MCUBOOT_INDICATION_LED`` Kconfig option to enable the LED. +By default, both the GPIO pin and the LED are defined in the board's DTS file. +See :file:`boards/arm/nrf52833dongle_nrf52833/nrf52833dongle_nrf52833.dts` for an example of board's DTS file used by the nRF Desktop application. + +For an example of bootloader Kconfig configuration file defined by the application, see the MCUboot bootloader ``debug`` configuration defined for nRF52833 dongle (:file:`applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf`). + +.. note:: + The nRF Desktop devices use either the serial recovery DFU with a single application slot or the background DFU. + Both mentioned firmware upgrade methods are not used simultaneously by any of the configurations. + For example, the ``nrf52840dk_nrf52840`` board in ``prj_mcuboot_smp.conf`` uses only the background DFU and does not enable the serial recovery feature. + +.. _nrf_desktop_bootloader_background_dfu: + +Background Device Firmware Upgrade +********************************** + +The nRF Desktop application uses the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu` for the background DFU process. +From the application perspective, the update image transfer during the background DFU process is very similar for all supported configurations: + +* MCUboot +* Secure Bootloader (B0) + +The firmware update process has the following three stages: + +* Update image generation +* Update image transfer +* Update image verification and application image update + +These stages are described in the following sections. + +At the end of these three stages, the nRF Desktop application will be rebooted with the new firmware package installed. + +.. note:: + The background firmware upgrade can also be performed over the Simple Management Protocol (SMP). + For more details about the DFU procedure over SMP, read the documentation of the following modules: + + * :ref:`nrf_desktop_ble_smp` (supported only with MCUboot bootloader) + * :ref:`nrf_desktop_dfu_mcumgr` (supported only with MCUboot bootloader) + The module uses the :ref:`nrf_desktop_dfu_lock` to synchronize non-volatile memory access with other DFU methods. + Therefore, this module should be used for configurations that enable multiple DFU transports (for example, if a configuration also enables :ref:`nrf_desktop_dfu`). + +Update image generation +======================= + +The update image is generated in the build directory when building the firmware regardless of the chosen DFU configuration. + +MCUboot and B0 bootloaders +-------------------------- + +The :file:`zephyr/dfu_application.zip` file is used by both B0 and MCUboot bootloader for the background DFU through the :ref:`nrf_desktop_config_channel` and :ref:`nrf_desktop_dfu`. +The package contains firmware images along with additional metadata. +If the used bootloader boots the application directly from either slot 0 or slot 1, the host script transfers the update image that can be run from the unused slot. +Otherwise, the image is always uploaded to the slot 1 and then moved to slot 0 by the bootloader before boot. + +.. note:: + Make sure to properly configure the bootloader to ensure that the build system generates the :file:`zephyr/dfu_application.zip` archive containing all of the required update images. + +Update image transfer +===================== + +The update image is transmitted in the background through the :ref:`nrf_desktop_config_channel`. +The configuration channel data is transmitted either through USB or over Bluetooth, using HID feature reports. +This allows the device to be used normally during the whole process (that is, the device does not need to enter any special state in which it becomes non-responsive to the user). + +Depending on the side on which the process is handled: + +* On the application side, the process is handled by :ref:`nrf_desktop_dfu`. + See the module documentation for how to enable and configure it. +* On the host side, the process is handled by the :ref:`nrf_desktop_config_channel_script`. + See the tool documentation for more information about how to execute the background DFU process on the host. + +.. _nrf_desktop_image_transfer_over_smp: + +Image transfer over SMP +----------------------- + +The update image can also be transferred in the background through one of the following modules: + +* :ref:`nrf_desktop_ble_smp` (supported only with MCUboot bootloader) +* :ref:`nrf_desktop_dfu_mcumgr` (supported only with MCUboot bootloader) + The module uses the :ref:`nrf_desktop_dfu_lock` to synchronize non-volatile memory access with other DFU methods. + Therefore, this module should be used for configurations that enable multiple DFU transports (for example, if a configuration also enables :ref:`nrf_desktop_dfu`). + +The `nRF Connect Device Manager`_ application transfers the image update files over the Simple Management Protocol (SMP). + +To perform DFU using the `nRF Connect Device Manager`_ mobile app, complete the following steps: + +.. include:: /device_guides/working_with_nrf/nrf52/developing.rst + :start-after: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_start + :end-before: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_end + +.. include:: /device_guides/working_with_nrf/nrf52/developing.rst + :start-after: fota_upgrades_over_ble_mcuboot_direct_xip_nrfcdm_note_start + :end-before: fota_upgrades_over_ble_mcuboot_direct_xip_nrfcdm_note_end + +.. note:: + If the :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT` Kconfig option is enabled in the application configuration, the device rejects update image upload for the invalid slot. + It is recommended to enable the option if the application uses MCUboot in the direct-xip mode. + +Update image verification and application image update +====================================================== + +Once the update image transfer is completed, the background DFU process will continue after the device reboot. +If :ref:`nrf_desktop_config_channel_script` is used, the reboot is triggered by the script right after the image transfer completes. + +The implementation details of the reboot mechanism for the chosen DFU configuration are described in the following subsections. + +MCUboot and B0 bootloaders +-------------------------- + +For these configuration variants, the :c:func:`sys_reboot` function is called to reboot the device. +After the reboot, the bootloader locates the update image on the update partition of the device. +The image verification process ensures the integrity of the image and checks if its signature is valid. +If verification is successful, the bootloader boots the new version of the application. +Otherwise, the old version is used. + +.. _nrf_desktop_bootloader_serial_dfu: + +Serial recovery DFU +******************** + +The serial recovery DFU is a feature of MCUboot and you need to enable it in the bootloader's configuration. +For the configuration details, see the :ref:`nrf_desktop_configuring_mcuboot_bootloader` section. + +To start the serial recovery DFU, the device should boot into recovery mode, in which the bootloader is waiting for a new image upload to start. +In the serial recovery DFU mode, the new image is transferred through an USB CDC ACM class instance. +The bootloader overwrites the existing application located on the primary slot with the new application image. +If the transfer is interrupted, the device cannot boot the incomplete application, and the image upload must be performed again. + +Once the device enters the serial recovery mode, you can use the :ref:`mcumgr ` to: + +* Query information about the present image. +* Upload the new image. + The :ref:`mcumgr ` uses the :file:`zephyr/app_update.bin` update image file. + It is generated by the build system when building the firmware. + +For example, the following line starts the upload of the new image to the device: + +.. code-block:: console + + mcumgr -t 60 --conntype serial --connstring=/dev/ttyACM0 image upload build-nrf52833dongle_nrf52833/zephyr/app_update.bin + +The command assumes that ``/dev/ttyACM0`` serial device is used by the MCUboot bootloader for the serial recovery. diff --git a/applications/nrf_desktop/configuration/nrf52820dongle_nrf52820/child_image/mcuboot/prj_release.conf b/applications/nrf_desktop/configuration/nrf52820dongle_nrf52820/child_image/mcuboot/prj_release.conf index 4a876367217..b3ff43fb5af 100644 --- a/applications/nrf_desktop/configuration/nrf52820dongle_nrf52820/child_image/mcuboot/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52820dongle_nrf52820/child_image/mcuboot/prj_release.conf @@ -63,3 +63,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_HASH=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52833dk_nrf52820/child_image/mcuboot/prj_release.conf b/applications/nrf_desktop/configuration/nrf52833dk_nrf52820/child_image/mcuboot/prj_release.conf index 6fb19a473b9..ae0c74c1ae7 100644 --- a/applications/nrf_desktop/configuration/nrf52833dk_nrf52820/child_image/mcuboot/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52833dk_nrf52820/child_image/mcuboot/prj_release.conf @@ -67,3 +67,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_HASH=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj.conf b/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj.conf index c8ef04e1c00..296a469b891 100644 --- a/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj.conf @@ -64,3 +64,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj_release.conf b/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj_release.conf index ad1009efaee..9a23ddcb488 100644 --- a/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52833dk_nrf52833/child_image/mcuboot/prj_release.conf @@ -61,3 +61,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf b/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf index c8ef04e1c00..296a469b891 100644 --- a/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj.conf @@ -64,3 +64,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj_release.conf b/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj_release.conf index 74bc334342d..dadb5cdbc5b 100644 --- a/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52833dongle_nrf52833/child_image/mcuboot/prj_release.conf @@ -60,3 +60,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj.conf index a3ee72771a6..ad366480bcb 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_dongle.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_dongle.conf index a3ee72771a6..ad366480bcb 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_dongle.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_dongle.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_keyboard.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_keyboard.conf index a3ee72771a6..ad366480bcb 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_keyboard.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_keyboard.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_release.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_release.conf index a3ee72771a6..7145ab14ce6 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_release.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_wwcb.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_wwcb.conf index 58405ded7be..11321fba9e3 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_wwcb.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/b0/prj_wwcb.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_fast_pair.conf index f521215e567..341958fff5d 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_fast_pair.conf @@ -25,7 +25,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private_fast_pair.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Reduce memory consumption @@ -39,3 +38,6 @@ CONFIG_NORDIC_QSPI_NOR=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_qspi.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_qspi.conf index 4b493b0b189..dcb2ee00337 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_qspi.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_qspi.conf @@ -52,3 +52,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf index a91b7562921..5e143ee16de 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf @@ -22,7 +22,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Logger @@ -37,3 +36,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj.conf index a58d9f0f595..1267a78d64f 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj.conf @@ -16,6 +16,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -42,6 +45,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_fast_pair.conf index df4ac2af21d..e693b7e5055 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_fast_pair.conf @@ -22,6 +22,9 @@ CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_DEVICE_GENERATION="FastPair" CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -64,6 +67,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=30 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_keyboard.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_keyboard.conf index 6b32172e34b..d6bce8e801c 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_keyboard.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_keyboard.conf @@ -19,6 +19,9 @@ CONFIG_DESKTOP_ROLE_HID_PERIPHERAL=y CONFIG_DESKTOP_PERIPHERAL_TYPE_KEYBOARD=y CONFIG_DESKTOP_DEVICE_PID=0x52DD CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD=y + +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 CONFIG_DESKTOP_HID_STATE_HID_KEYMAP_DEF_PATH="hid_keymap_def_keyboard.h" CONFIG_DESKTOP_HID_STATE_HID_KEYBOARD_LEDS_DEF_PATH="hid_keyboard_leds_def_keyboard.h" CONFIG_DESKTOP_HID_REPORT_EXPIRATION=10000 @@ -49,6 +52,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_qspi.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_qspi.conf index 1d53e11d75c..109fc076caa 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_qspi.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_qspi.conf @@ -20,6 +20,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -46,6 +49,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_smp.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_smp.conf index ae2b6771671..3e16613868c 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_smp.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_mcuboot_smp.conf @@ -21,6 +21,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -50,6 +53,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_release.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_release.conf index da9c05a8f22..9b8f067d780 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_release.conf @@ -11,6 +11,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -38,6 +41,7 @@ CONFIG_DESKTOP_WATCHDOG_ENABLE=y CONFIG_DESKTOP_FAILSAFE_ENABLE=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_wwcb.conf b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_wwcb.conf index 824ebda8b44..839d7bc7094 100644 --- a/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_wwcb.conf +++ b/applications/nrf_desktop/configuration/nrf52840dk_nrf52840/prj_wwcb.conf @@ -16,6 +16,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 @@ -48,6 +51,7 @@ CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_HFCLK_LOCK_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj.conf b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj.conf index 6ee3750dd86..92df3d15027 100644 --- a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj.conf @@ -43,3 +43,6 @@ CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_3bleconn.conf b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_3bleconn.conf index 6ee3750dd86..92df3d15027 100644 --- a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_3bleconn.conf +++ b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_3bleconn.conf @@ -43,3 +43,6 @@ CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_4llpmconn.conf b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_4llpmconn.conf index 6ee3750dd86..92df3d15027 100644 --- a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_4llpmconn.conf +++ b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_4llpmconn.conf @@ -43,3 +43,6 @@ CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release.conf b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release.conf index 6ee3750dd86..b01cc41b0fb 100644 --- a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release.conf @@ -43,3 +43,6 @@ CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release_4llpmconn.conf b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release_4llpmconn.conf index 6ee3750dd86..b01cc41b0fb 100644 --- a/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release_4llpmconn.conf +++ b/applications/nrf_desktop/configuration/nrf52840dongle_nrf52840/child_image/b0/prj_release_4llpmconn.conf @@ -43,3 +43,6 @@ CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj.conf index a3ee72771a6..ad366480bcb 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj_release.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj_release.conf index a3ee72771a6..7145ab14ce6 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/b0/prj_release.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_fast_pair.conf index ba545b2ddf9..b15058cf380 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_fast_pair.conf @@ -25,7 +25,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private_fast_pair.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Reduce memory consumption @@ -33,3 +32,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf index 89196cf3715..64b67bddbd8 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_mcuboot_smp.conf @@ -20,7 +20,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Decrease memory footprint @@ -31,7 +30,6 @@ CONFIG_SERIAL=n CONFIG_USE_SEGGER_RTT=n CONFIG_ERRNO=n CONFIG_PRINTK=n -CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_CBPRINTF_NANO=y CONFIG_TIMESLICING=n CONFIG_ARM_MPU=n @@ -39,3 +37,6 @@ CONFIG_THREAD_STACK_INFO=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_release_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_release_fast_pair.conf index ba545b2ddf9..be69f05f073 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_release_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/child_image/mcuboot/prj_release_fast_pair.conf @@ -25,7 +25,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private_fast_pair.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Reduce memory consumption @@ -33,3 +32,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj.conf index 0a84d508bd9..bde0cf2599a 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj.conf @@ -16,6 +16,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_WHEEL_ENABLE=y CONFIG_DESKTOP_WHEEL_SENSOR_VALUE_DIVIDER=15 diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_fast_pair.conf index 2226ea740ec..6054e38aea9 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_fast_pair.conf @@ -22,6 +22,9 @@ CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_DEVICE_GENERATION="FastPair" CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_WHEEL_ENABLE=y CONFIG_DESKTOP_WHEEL_SENSOR_VALUE_DIVIDER=15 @@ -78,7 +81,7 @@ CONFIG_CAF_BLE_ADV_FILTER_ACCEPT_LIST=n CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS=3 # Align the advertised TX power with Fast Pair expectations. -CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL=-18 +CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL=-11 CONFIG_DESKTOP_BLE_USE_DEFAULT_ID=y diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_mcuboot_smp.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_mcuboot_smp.conf index e3284d0c962..9270a0a79cb 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_mcuboot_smp.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_mcuboot_smp.conf @@ -21,6 +21,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_WHEEL_ENABLE=y CONFIG_DESKTOP_WHEEL_SENSOR_VALUE_DIVIDER=15 diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release.conf index b2734e10bff..8a4f37a9375 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release.conf @@ -11,6 +11,9 @@ CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_WHEEL_ENABLE=y CONFIG_DESKTOP_WHEEL_SENSOR_VALUE_DIVIDER=15 diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release_fast_pair.conf index 478b635ea19..ea47f85af50 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/prj_release_fast_pair.conf @@ -17,6 +17,9 @@ CONFIG_DESKTOP_DEVICE_PID=0x52DE CONFIG_DESKTOP_DEVICE_GENERATION="FastPair" CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y +# Application supports 2 HID subscribers: HID over GATT (BLE) and a single USB HID instance +CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT=2 + CONFIG_DESKTOP_WHEEL_ENABLE=y CONFIG_DESKTOP_WHEEL_SENSOR_VALUE_DIVIDER=15 @@ -71,7 +74,7 @@ CONFIG_CAF_BLE_ADV_FILTER_ACCEPT_LIST=n CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS=3 # Align the advertised TX power with Fast Pair expectations. -CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL=-18 +CONFIG_BT_ADV_PROV_TX_POWER_CORRECTION_VAL=-11 CONFIG_DESKTOP_BLE_PEER_CONTROL=y CONFIG_DESKTOP_BLE_PEER_CONTROL_BUTTON=0x0007 diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/b0/prj_release.conf b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/b0/prj_release.conf index a3ee72771a6..7145ab14ce6 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/b0/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/b0/prj_release.conf @@ -37,3 +37,6 @@ CONFIG_ASSERT=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/mcuboot/prj_release_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/mcuboot/prj_release_fast_pair.conf index ba545b2ddf9..be69f05f073 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/mcuboot/prj_release_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/child_image/mcuboot/prj_release_fast_pair.conf @@ -25,7 +25,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private_fast_pair.pem" # Flash CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y # Reduce memory consumption @@ -33,3 +32,6 @@ CONFIG_BOOT_BANNER=n # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj.conf b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj.conf index 7baef301a38..95a3919183e 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj.conf +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj.conf @@ -49,6 +49,7 @@ CONFIG_DESKTOP_BLE_ENABLE_PASSKEY=y CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_FN_KEYS_ENABLE=y CONFIG_DESKTOP_FN_KEYS_SWITCH=0x111 diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release.conf b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release.conf index 032193ce15b..aebcfedd5a0 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release.conf @@ -45,6 +45,7 @@ CONFIG_DESKTOP_WATCHDOG_ENABLE=y CONFIG_DESKTOP_FAILSAFE_ENABLE=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_FN_KEYS_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release_fast_pair.conf b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release_fast_pair.conf index 1a8ecfb1a53..40043c3189f 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release_fast_pair.conf +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/prj_release_fast_pair.conf @@ -62,6 +62,7 @@ CONFIG_DESKTOP_WATCHDOG_ENABLE=y CONFIG_DESKTOP_FAILSAFE_ENABLE=y CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y CONFIG_DESKTOP_FN_KEYS_ENABLE=y diff --git a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj.conf b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj.conf index 569e6cec4c7..2ff1c8bb9c3 100644 --- a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj.conf +++ b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj.conf @@ -40,3 +40,6 @@ CONFIG_MINIMAL_LIBC=y # The anomaly 160 workaround is not needed for the bootloader. CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED=n + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj_release.conf b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj_release.conf index 569e6cec4c7..0aec50c7299 100644 --- a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/b0/prj_release.conf @@ -40,3 +40,6 @@ CONFIG_MINIMAL_LIBC=y # The anomaly 160 workaround is not needed for the bootloader. CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED=n + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf index bf0d0e351d1..aeef4577fea 100644 --- a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf +++ b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj.conf @@ -36,3 +36,6 @@ CONFIG_EXCEPTION_STACK_TRACE=y # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf index 7a49453f731..2a4457f995b 100644 --- a/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf +++ b/applications/nrf_desktop/configuration/nrf5340dk_nrf5340_cpuapp/child_image/hci_ipc/prj_release.conf @@ -32,3 +32,6 @@ CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT=3000 # Use minimal C library instead of the Picolib CONFIG_MINIMAL_LIBC=y + +# Improve firmware reliability +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.conf new file mode 100644 index 00000000000..71aaae452f0 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.conf @@ -0,0 +1,15 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ + +# GPIOs assigned to Button 3 and Button 4 on the PDK v0.2.x do not support interrupts. +# Because of this, the GPIOs are not supported by the CAF buttons module and cannot be used to +# generate motion. +CONFIG_CAF_BUTTONS_DEF_PATH="buttons_def_0_2_0.h" +CONFIG_DESKTOP_MOTION_BUTTONS_LEFT_KEY_ID=0 +CONFIG_DESKTOP_MOTION_BUTTONS_RIGHT_KEY_ID=1 +CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=2 +CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.overlay b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.overlay new file mode 100644 index 00000000000..b9b1c91f8a5 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0.overlay @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* For nRF54L, watchdog status is disabled by default. Needs to be enabled in DTS overlay. */ +&wdt30 { + status = "okay"; +}; + +/ { + /* Disable leds and redefine them to align configuration with CAF LEDs requirements. + * The configuration needs to match the used board revision (v0.2.0). + */ + leds { + status = "disabled"; + }; + + gpioled0 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED System State"; + + led0_g: led_0 { + gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + }; + + gpioled1 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Conn State"; + + led1_g: led_1 { + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + }; + + gpioled2 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Num Lock"; + + led2_g: led_2 { + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + }; + + gpioled3 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Caps Lock"; + + led3_g: led_3 { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_keyboard.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_keyboard.conf new file mode 100644 index 00000000000..6c689b77a2b --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_keyboard.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ + + +# GPIOs assigned to Button 3 and Button 4 on the PDK v0.2.x do not support interrupts. +# Because of this, the GPIOs are not supported by the CAF buttons module and cannot be used to +# generate keypresses. +CONFIG_CAF_BUTTONS_DEF_PATH="buttons_def_0_2_0.h" +CONFIG_DESKTOP_HID_STATE_HID_KEYMAP_DEF_PATH="hid_keymap_def_keyboard_0_2_0.h" +CONFIG_DESKTOP_BUTTONS_SIM_TRIGGER_KEY_ID=0x01 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_release.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_release.conf new file mode 100644 index 00000000000..71aaae452f0 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_2_0_release.conf @@ -0,0 +1,15 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ + +# GPIOs assigned to Button 3 and Button 4 on the PDK v0.2.x do not support interrupts. +# Because of this, the GPIOs are not supported by the CAF buttons module and cannot be used to +# generate motion. +CONFIG_CAF_BUTTONS_DEF_PATH="buttons_def_0_2_0.h" +CONFIG_DESKTOP_MOTION_BUTTONS_LEFT_KEY_ID=0 +CONFIG_DESKTOP_MOTION_BUTTONS_RIGHT_KEY_ID=1 +CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=2 +CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay new file mode 100644 index 00000000000..11ab3d3b805 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "nrf54l15pdk_nrf54l15_cpuapp_0_3_0_fixup.dtsi" + +/* For nRF54L, watchdog status is disabled by default. Needs to be enabled in DTS overlay. */ +&wdt30 { + status = "okay"; +}; + +/ { + /* Disable leds and redefine them to align configuration with CAF LEDs requirements. + * The configuration needs to match the used board revision (v0.3.0). + */ + leds { + status = "disabled"; + }; + + gpioled0 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED System State"; + + led0_g: led_0 { + gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + }; + + gpioled1 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Conn State"; + + led1_g: led_1 { + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + }; + + gpioled2 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Num Lock"; + + led2_g: led_2 { + gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + }; + + gpioled3 { + compatible = "gpio-leds"; + status = "okay"; + label = "LED Caps Lock"; + + led3_g: led_3 { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0_fixup.dtsi b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0_fixup.dtsi new file mode 100644 index 00000000000..bf0931cdfb0 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/boards/nrf54l15pdk_nrf54l15_cpuapp_0_3_0_fixup.dtsi @@ -0,0 +1,44 @@ +/* Ths file content is copied from the "nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay" file defined in + * nrf54l15pdk_nrf54l15 board directory. The file from the board directory is not automatically used + * e.g. for mcuboot_secondary_app child image. Application applies content of the file manually to + * workaround the problem. + */ + +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + +&led0 { + gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; +}; + +&led1 { + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; +}; + +&led2 { + gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>; +}; + +&led3 { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; +}; + +&button0 { + gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button1 { + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button2 { + gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button3 { + gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def.h new file mode 100644 index 00000000000..5aee49473ef --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/* This configuration file is included only once from button module and holds + * information about pins forming keyboard matrix. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} buttons_def_include_once; + +static const struct gpio_pin col[] = {}; + +static const struct gpio_pin row[] = { + { .port = 1, .pin = DT_GPIO_PIN(DT_NODELABEL(button0), gpios) }, + { .port = 1, .pin = DT_GPIO_PIN(DT_NODELABEL(button1), gpios) }, + { .port = 1, .pin = DT_GPIO_PIN(DT_NODELABEL(button2), gpios) }, + { .port = 0, .pin = DT_GPIO_PIN(DT_NODELABEL(button3), gpios) }, +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def_0_2_0.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def_0_2_0.h new file mode 100644 index 00000000000..6187040060d --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_def_0_2_0.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/* This configuration file is included only once from button module and holds + * information about pins forming keyboard matrix. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} buttons_def_include_once; + +static const struct gpio_pin col[] = {}; + +static const struct gpio_pin row[] = { + { .port = 1, .pin = DT_GPIO_PIN(DT_NODELABEL(button0), gpios) }, + { .port = 1, .pin = DT_GPIO_PIN(DT_NODELABEL(button1), gpios) }, + /* GPIOs assigned to Button 3 and Button 4 on the PDK v0.2.x do not support interrupts. + * Because of this, the GPIOs cannot be used by the CAF buttons module. + */ +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_sim_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_sim_def.h new file mode 100644 index 00000000000..b6a008dc168 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/buttons_sim_def.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/* This configuration file is included only once from buttons_sim module + * and holds information about generated button presses sequence. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} buttons_sim_def_include_once; + +const static uint16_t simulated_key_sequence[] = { + KEY_ID(0x00, 0x11), /* N */ + KEY_ID(0x00, 0x12), /* O */ + KEY_ID(0x00, 0x15), /* R */ + KEY_ID(0x00, 0x07), /* D */ + KEY_ID(0x00, 0x0C), /* I */ + KEY_ID(0x00, 0x06), /* C */ + KEY_ID(0x00, 0x2C), /* spacebar */ +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/mcuboot_private.pem b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/mcuboot_private.pem new file mode 100644 index 00000000000..af30c7b46e0 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/mcuboot_private.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDMgpljNyVhjcme +L5w3afeB45AuxOKocy4y/WCbAgH5fWU6KP4E3DNCbKsta17hyZyzfC0QJl4gJK8Z +76FmGNHEv3Xg5ZXBLRo8SDak0zqCkhprx70m8xSEx6sxCPDFndYECluv/G0XPvIz +dQJ9yQdHHv78niAJQoGCf/0D4NjrTj5GIMSmyh1bssmi1j6TxrBXH+eplfyeuhbK +DlagXRjTXOBtyNY7SSAhDZX0xCIdLWJ5GLyRmKvX4HXvhdFjuBwdQmfBggU37gPz +mvhnell2c2Fyd/zcefl9H8paKFiIJd16GcJfmlO5zR++JhME+tGO92+dnp51NrE5 +jD7JvDBHAgMBAAECggEABeKCLcKHTwHTTzvOfSJi+WKwzO+5wqAh2wdt0WK4PNN4 +vLjeP7SNvbe+dehKNX662sf+zKFWAbXHMMdeTRT3avfEGWxx0o+3hWGMlPybs+h8 +CHrvEfZaXPcZPCgmNCw2XYJmIK/HpyzBWm1fsiU9PN+C9dufpLSRtngeseRf9DwM +eG6Et2J5RLxeTHk6J7FhLK0peW3Str3Mrc3eqcRM/AvdKlEwjL/lUjrsIAIBYpwQ +fl62E00MsTmFu/35iVlPHIWRstZ0NZxwfVJKjunoSIiUTI33KrB2RiNR6hcXSN/B +LnzvVO71mHr41R6IvDbmorGR+dekA5kPXTCsQ6qoZQKBgQDcv4BgiG5kCEVXqHla +M/dsAsXX1u2+uftIL+7UbpCdwmNf8jm5nAyIU5RomGD2+sWdUXGd5urUYALLuzms +WpL19RuKp+uwueJ2Gj6Onbn0ZrUzz92+0nL73hdQVXFuHFFrRT/1p3NZn8ApA7wN +X2Fvw71Zmg64WAmFEdzSV19W6wKBgQDtK0TagT+OztmcIHtw1w94uJRSqrqvKtXT +yqtba23aKBhbJlQOccpw6oNgxiQJf48CnOO3bY1r08i4RmQ8efNs0IYhKwhrslVj +TTUP9lmJxFpbi6ABFufuih1xV7lr4qCme2yoyU6/Wm6GXGF9WAAHU7HQ88EPPHTg +MS7DKrhtFQKBgHxM3RX+XOK5AYrdlA+l6XGJkiv6m37lLMi2LO6zn30l4104gSax +5yCwp4XKH/eSt8ng/XAjgiG6OnjL4SrbCZuzvCF0crPdx9Ym6wjVactkNi6Jotx7 +lkGbCley9R9ClNopcV17P+m8mbC+qJqDFdOgTbPxms5UzG+A4m4Swt2nAoGAPD1P +QciuYhF8CEHf2KtnTJxlYBHpVPCmWyMRHylMP6sLdKtpkjmo18FZGU16fcceheVf +mYmD8C1cwCFw+ENpZuwYBXiurNwhABXuMl26JFnxMWtnep9czaPbEpzbheGMOH0E +/mITVFsd05bHVFTzvOivM4mWMc6DSSZ04DGLonkCgYBtEF1taMXwOQWiN5feFDPJ +tsBjeONi4n0oUcYmm9zRuvTgP3CswK5B4yFWTZ+UcDwAyg6jeFT9kKeB5TA+i0mE +0XOEZA+X0ybm/V1gERliQqyKQ38waNjlXeM3fYfD/KFBpmtXZB+hjebfXBVggzyA +WBbUOJ/pM1gbI8wtH4kyOw== +-----END PRIVATE KEY----- diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj.conf new file mode 100644 index 00000000000..fe3fdc1383b --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj.conf @@ -0,0 +1,41 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_SIZE_OPTIMIZATIONS=y + +# Disable memory guard to avoid false faults in application after boot +CONFIG_HW_STACK_PROTECTION=n + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=256 +CONFIG_BOOT_BOOTSTRAP=n + +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_BOOT_VERSION_CMP_USE_BUILD_NUMBER=y + +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n +CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private.pem" + +# Flash +CONFIG_FLASH=y + +# Reduce memory consumption +CONFIG_BOOT_BANNER=n +CONFIG_GPIO=n +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_keyboard.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_keyboard.conf new file mode 100644 index 00000000000..fe3fdc1383b --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_keyboard.conf @@ -0,0 +1,41 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_SIZE_OPTIMIZATIONS=y + +# Disable memory guard to avoid false faults in application after boot +CONFIG_HW_STACK_PROTECTION=n + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=256 +CONFIG_BOOT_BOOTSTRAP=n + +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_BOOT_VERSION_CMP_USE_BUILD_NUMBER=y + +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n +CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private.pem" + +# Flash +CONFIG_FLASH=y + +# Reduce memory consumption +CONFIG_BOOT_BANNER=n +CONFIG_GPIO=n +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_release.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_release.conf new file mode 100644 index 00000000000..fe3fdc1383b --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/child_image/mcuboot/prj_release.conf @@ -0,0 +1,41 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_SIZE_OPTIMIZATIONS=y + +# Disable memory guard to avoid false faults in application after boot +CONFIG_HW_STACK_PROTECTION=n + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=256 +CONFIG_BOOT_BOOTSTRAP=n + +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_BOOT_VERSION_CMP_USE_BUILD_NUMBER=y + +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n +CONFIG_BOOT_SIGNATURE_KEY_FILE="mcuboot_private.pem" + +# Flash +CONFIG_FLASH=y + +# Reduce memory consumption +CONFIG_BOOT_BANNER=n +CONFIG_GPIO=n +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Improve debugging experience by disabling reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/click_detector_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/click_detector_def.h new file mode 100644 index 00000000000..38a3fee1443 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/click_detector_def.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/* This configuration file is included only once from click_detector module + * and holds information about click detector configuration. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} click_detector_def_include_once; + +static const struct click_detector_config click_detector_config[] = { + { + .key_id = CONFIG_DESKTOP_BLE_PEER_CONTROL_BUTTON, + .consume_button_event = false, + }, +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def.h new file mode 100644 index 00000000000..445b2f14943 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "hid_keyboard_leds.h" + +/* This configuration file is included only once from hid_state module and holds + * information about LEDs associated with HID keyboard LEDs report. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} hid_keyboard_leds_def_include_once; + +static const struct led_effect keyboard_led_on = LED_EFFECT_LED_ON(LED_COLOR(255, 255, 255)); +static const struct led_effect keyboard_led_off = LED_EFFECT_LED_OFF(); + +/* Map HID keyboard LEDs to application LED IDs. */ +static const uint8_t keyboard_led_map[] = { +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def_keyboard.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def_keyboard.h new file mode 100644 index 00000000000..3292b1cb619 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keyboard_leds_def_keyboard.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "hid_keyboard_leds.h" + +/* This configuration file is included only once from hid_state module and holds + * information about LEDs associated with HID keyboard LEDs report. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} hid_keyboard_leds_def_include_once; + +static const struct led_effect keyboard_led_on = LED_EFFECT_LED_ON(LED_COLOR(255, 255, 255)); +static const struct led_effect keyboard_led_off = LED_EFFECT_LED_OFF(); + +/* Map HID keyboard LEDs to application LED IDs. */ +static const uint8_t keyboard_led_map[] = { + [HID_KEYBOARD_LEDS_NUM_LOCK] = 2, + [HID_KEYBOARD_LEDS_CAPS_LOCK] = 3, + [HID_KEYBOARD_LEDS_SCROLL_LOCK] = LED_UNAVAILABLE, + [HID_KEYBOARD_LEDS_COMPOSE] = LED_UNAVAILABLE, + [HID_KEYBOARD_LEDS_KANA] = LED_UNAVAILABLE, +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def.h new file mode 100644 index 00000000000..08cd2cfdae9 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "hid_keymap.h" +#include + +/* This configuration file is included only once from hid_state module and holds + * information about mapping between buttons and generated reports. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} hid_keymap_def_include_once; + +/* + * HID keymap. The Consumer Control keys are defined in section 15 of + * the HID Usage Tables document under the following URL: + * https://www.usb.org/sites/default/files/hut1_12.pdf + */ +static const struct hid_keymap hid_keymap[] = { + /* Intentionally left empty. nRF54L PDK by default uses all buttons only to control + * generating motion. + */ +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard.h new file mode 100644 index 00000000000..02dff560c18 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "hid_keymap.h" +#include + +/* This configuration file is included only once from hid_state module and holds + * information about mapping between buttons and generated reports. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} hid_keymap_def_include_once; + +/* + * HID keymap. The Consumer Control keys are defined in section 15 of + * the HID Usage Tables document under the following URL: + * https://www.usb.org/sites/default/files/hut1_12.pdf + */ +static const struct hid_keymap hid_keymap[] = { + { KEY_ID(0x00, 0x00), 0x0004, REPORT_ID_KEYBOARD_KEYS }, /* A */ + { KEY_ID(0x00, 0x01), 0x0005, REPORT_ID_KEYBOARD_KEYS }, /* B */ + { KEY_ID(0x00, 0x02), 0x00E1, REPORT_ID_KEYBOARD_KEYS }, /* left shift */ + + { KEY_ID(0x00, 0x04), 0x0004, REPORT_ID_KEYBOARD_KEYS }, /* A */ + { KEY_ID(0x00, 0x05), 0x0005, REPORT_ID_KEYBOARD_KEYS }, /* B */ + { KEY_ID(0x00, 0x06), 0x0006, REPORT_ID_KEYBOARD_KEYS }, /* C */ + { KEY_ID(0x00, 0x07), 0x0007, REPORT_ID_KEYBOARD_KEYS }, /* D */ + { KEY_ID(0x00, 0x08), 0x0008, REPORT_ID_KEYBOARD_KEYS }, /* E */ + { KEY_ID(0x00, 0x09), 0x0009, REPORT_ID_KEYBOARD_KEYS }, /* F */ + { KEY_ID(0x00, 0x0A), 0x000A, REPORT_ID_KEYBOARD_KEYS }, /* G */ + { KEY_ID(0x00, 0x0B), 0x000B, REPORT_ID_KEYBOARD_KEYS }, /* H */ + { KEY_ID(0x00, 0x0C), 0x000C, REPORT_ID_KEYBOARD_KEYS }, /* I */ + { KEY_ID(0x00, 0x0D), 0x000D, REPORT_ID_KEYBOARD_KEYS }, /* J */ + { KEY_ID(0x00, 0x0E), 0x000E, REPORT_ID_KEYBOARD_KEYS }, /* K */ + { KEY_ID(0x00, 0x0F), 0x000F, REPORT_ID_KEYBOARD_KEYS }, /* L */ + { KEY_ID(0x00, 0x10), 0x0010, REPORT_ID_KEYBOARD_KEYS }, /* M */ + { KEY_ID(0x00, 0x11), 0x0011, REPORT_ID_KEYBOARD_KEYS }, /* N */ + { KEY_ID(0x00, 0x12), 0x0012, REPORT_ID_KEYBOARD_KEYS }, /* O */ + { KEY_ID(0x00, 0x13), 0x0013, REPORT_ID_KEYBOARD_KEYS }, /* P */ + { KEY_ID(0x00, 0x14), 0x0014, REPORT_ID_KEYBOARD_KEYS }, /* Q */ + { KEY_ID(0x00, 0x15), 0x0015, REPORT_ID_KEYBOARD_KEYS }, /* R */ + { KEY_ID(0x00, 0x16), 0x0016, REPORT_ID_KEYBOARD_KEYS }, /* S */ + { KEY_ID(0x00, 0x17), 0x0017, REPORT_ID_KEYBOARD_KEYS }, /* T */ + { KEY_ID(0x00, 0x18), 0x0018, REPORT_ID_KEYBOARD_KEYS }, /* U */ + { KEY_ID(0x00, 0x19), 0x0019, REPORT_ID_KEYBOARD_KEYS }, /* V */ + { KEY_ID(0x00, 0x1A), 0x001A, REPORT_ID_KEYBOARD_KEYS }, /* W */ + { KEY_ID(0x00, 0x1B), 0x001B, REPORT_ID_KEYBOARD_KEYS }, /* X */ + { KEY_ID(0x00, 0x1C), 0x001C, REPORT_ID_KEYBOARD_KEYS }, /* Y */ + { KEY_ID(0x00, 0x1D), 0x001D, REPORT_ID_KEYBOARD_KEYS }, /* Z */ + + { KEY_ID(0x00, 0x2C), 0x002C, REPORT_ID_KEYBOARD_KEYS }, /* spacebar */ +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard_0_2_0.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard_0_2_0.h new file mode 100644 index 00000000000..7720cc8331b --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/hid_keymap_def_keyboard_0_2_0.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "hid_keymap.h" +#include + +/* This configuration file is included only once from hid_state module and holds + * information about mapping between buttons and generated reports. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} hid_keymap_def_include_once; + +/* + * HID keymap. The Consumer Control keys are defined in section 15 of + * the HID Usage Tables document under the following URL: + * https://www.usb.org/sites/default/files/hut1_12.pdf + */ +static const struct hid_keymap hid_keymap[] = { + { KEY_ID(0x00, 0x00), 0x0004, REPORT_ID_KEYBOARD_KEYS }, /* A */ + + { KEY_ID(0x00, 0x04), 0x0004, REPORT_ID_KEYBOARD_KEYS }, /* A */ + { KEY_ID(0x00, 0x05), 0x0005, REPORT_ID_KEYBOARD_KEYS }, /* B */ + { KEY_ID(0x00, 0x06), 0x0006, REPORT_ID_KEYBOARD_KEYS }, /* C */ + { KEY_ID(0x00, 0x07), 0x0007, REPORT_ID_KEYBOARD_KEYS }, /* D */ + { KEY_ID(0x00, 0x08), 0x0008, REPORT_ID_KEYBOARD_KEYS }, /* E */ + { KEY_ID(0x00, 0x09), 0x0009, REPORT_ID_KEYBOARD_KEYS }, /* F */ + { KEY_ID(0x00, 0x0A), 0x000A, REPORT_ID_KEYBOARD_KEYS }, /* G */ + { KEY_ID(0x00, 0x0B), 0x000B, REPORT_ID_KEYBOARD_KEYS }, /* H */ + { KEY_ID(0x00, 0x0C), 0x000C, REPORT_ID_KEYBOARD_KEYS }, /* I */ + { KEY_ID(0x00, 0x0D), 0x000D, REPORT_ID_KEYBOARD_KEYS }, /* J */ + { KEY_ID(0x00, 0x0E), 0x000E, REPORT_ID_KEYBOARD_KEYS }, /* K */ + { KEY_ID(0x00, 0x0F), 0x000F, REPORT_ID_KEYBOARD_KEYS }, /* L */ + { KEY_ID(0x00, 0x10), 0x0010, REPORT_ID_KEYBOARD_KEYS }, /* M */ + { KEY_ID(0x00, 0x11), 0x0011, REPORT_ID_KEYBOARD_KEYS }, /* N */ + { KEY_ID(0x00, 0x12), 0x0012, REPORT_ID_KEYBOARD_KEYS }, /* O */ + { KEY_ID(0x00, 0x13), 0x0013, REPORT_ID_KEYBOARD_KEYS }, /* P */ + { KEY_ID(0x00, 0x14), 0x0014, REPORT_ID_KEYBOARD_KEYS }, /* Q */ + { KEY_ID(0x00, 0x15), 0x0015, REPORT_ID_KEYBOARD_KEYS }, /* R */ + { KEY_ID(0x00, 0x16), 0x0016, REPORT_ID_KEYBOARD_KEYS }, /* S */ + { KEY_ID(0x00, 0x17), 0x0017, REPORT_ID_KEYBOARD_KEYS }, /* T */ + { KEY_ID(0x00, 0x18), 0x0018, REPORT_ID_KEYBOARD_KEYS }, /* U */ + { KEY_ID(0x00, 0x19), 0x0019, REPORT_ID_KEYBOARD_KEYS }, /* V */ + { KEY_ID(0x00, 0x1A), 0x001A, REPORT_ID_KEYBOARD_KEYS }, /* W */ + { KEY_ID(0x00, 0x1B), 0x001B, REPORT_ID_KEYBOARD_KEYS }, /* X */ + { KEY_ID(0x00, 0x1C), 0x001C, REPORT_ID_KEYBOARD_KEYS }, /* Y */ + { KEY_ID(0x00, 0x1D), 0x001D, REPORT_ID_KEYBOARD_KEYS }, /* Z */ + + { KEY_ID(0x00, 0x2C), 0x002C, REPORT_ID_KEYBOARD_KEYS }, /* spacebar */ +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/led_state_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/led_state_def.h new file mode 100644 index 00000000000..7fdac8b5b42 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/led_state_def.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "led_state.h" +#include + +/* This configuration file is included only once from led_state module and holds + * information about LED effect associated with each state. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} led_state_def_include_once; + + +/* Map function to LED ID */ +static const uint8_t led_map[LED_ID_COUNT] = { + [LED_ID_SYSTEM_STATE] = 0, + [LED_ID_PEER_STATE] = 1 +}; + +static const struct led_effect led_system_state_effect[LED_SYSTEM_STATE_COUNT] = { + [LED_SYSTEM_STATE_IDLE] = LED_EFFECT_LED_ON(LED_COLOR(200, 200, 200)), + [LED_SYSTEM_STATE_CHARGING] = LED_EFFECT_LED_ON(LED_COLOR(200, 200, 200)), + [LED_SYSTEM_STATE_ERROR] = LED_EFFECT_LED_BLINK(200, LED_COLOR(200, 200, 200)), +}; + +static const struct led_effect led_peer_state_effect[LED_PEER_COUNT][LED_PEER_STATE_COUNT] = { + {[LED_PEER_STATE_DISCONNECTED] = LED_EFFECT_LED_OFF(), + [LED_PEER_STATE_CONNECTED] = LED_EFFECT_LED_ON(LED_COLOR(100, 100, 100)), + [LED_PEER_STATE_PEER_SEARCH] = LED_EFFECT_LED_BREATH(1000, LED_COLOR(100, 100, 100)), + [LED_PEER_STATE_CONFIRM_SELECT] = LED_EFFECT_LED_BLINK(50, LED_COLOR(100, 100, 100)), + [LED_PEER_STATE_CONFIRM_ERASE] = LED_EFFECT_LED_BLINK(25, LED_COLOR(100, 100, 100)), + [LED_PEER_STATE_ERASE_ADV] = LED_EFFECT_LED_BREATH(100, LED_COLOR(100, 100, 100)), + }, +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static.yml b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static.yml new file mode 100644 index 00000000000..0525b519b52 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static.yml @@ -0,0 +1,47 @@ +app: + address: 0x8800 + region: flash_primary + size: 0xb7800 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x8000 +mcuboot_pad: + address: 0x8000 + region: flash_primary + size: 0x800 +mcuboot_primary: + address: 0x8000 + orig_span: &id001 + - app + - mcuboot_pad + region: flash_primary + size: 0xb8000 + span: *id001 +mcuboot_primary_app: + address: 0x8800 + orig_span: &id002 + - app + region: flash_primary + size: 0xb7800 + span: *id002 +mcuboot_secondary: + address: 0xc0000 + orig_span: &id003 + - mcuboot_secondary_pad + - mcuboot_secondary_app + region: flash_primary + size: 0xb8000 + span: *id003 +mcuboot_secondary_pad: + region: flash_primary + address: 0xc0000 + size: 0x800 +mcuboot_secondary_app: + region: flash_primary + address: 0xc0800 + size: 0xb7800 +settings_storage: + address: 0x178000 + region: flash_primary + size: 0x5000 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_keyboard.yml b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_keyboard.yml new file mode 100644 index 00000000000..0525b519b52 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_keyboard.yml @@ -0,0 +1,47 @@ +app: + address: 0x8800 + region: flash_primary + size: 0xb7800 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x8000 +mcuboot_pad: + address: 0x8000 + region: flash_primary + size: 0x800 +mcuboot_primary: + address: 0x8000 + orig_span: &id001 + - app + - mcuboot_pad + region: flash_primary + size: 0xb8000 + span: *id001 +mcuboot_primary_app: + address: 0x8800 + orig_span: &id002 + - app + region: flash_primary + size: 0xb7800 + span: *id002 +mcuboot_secondary: + address: 0xc0000 + orig_span: &id003 + - mcuboot_secondary_pad + - mcuboot_secondary_app + region: flash_primary + size: 0xb8000 + span: *id003 +mcuboot_secondary_pad: + region: flash_primary + address: 0xc0000 + size: 0x800 +mcuboot_secondary_app: + region: flash_primary + address: 0xc0800 + size: 0xb7800 +settings_storage: + address: 0x178000 + region: flash_primary + size: 0x5000 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_release.yml b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_release.yml new file mode 100644 index 00000000000..0525b519b52 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/pm_static_release.yml @@ -0,0 +1,47 @@ +app: + address: 0x8800 + region: flash_primary + size: 0xb7800 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x8000 +mcuboot_pad: + address: 0x8000 + region: flash_primary + size: 0x800 +mcuboot_primary: + address: 0x8000 + orig_span: &id001 + - app + - mcuboot_pad + region: flash_primary + size: 0xb8000 + span: *id001 +mcuboot_primary_app: + address: 0x8800 + orig_span: &id002 + - app + region: flash_primary + size: 0xb7800 + span: *id002 +mcuboot_secondary: + address: 0xc0000 + orig_span: &id003 + - mcuboot_secondary_pad + - mcuboot_secondary_app + region: flash_primary + size: 0xb8000 + span: *id003 +mcuboot_secondary_pad: + region: flash_primary + address: 0xc0000 + size: 0x800 +mcuboot_secondary_app: + region: flash_primary + address: 0xc0800 + size: 0xb7800 +settings_storage: + address: 0x178000 + region: flash_primary + size: 0x5000 diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/port_state_def.h b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/port_state_def.h new file mode 100644 index 00000000000..30d47da1429 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/port_state_def.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#include "port_state.h" + +/* This configuration file is included only once from board module and holds + * information about default pin states set while board is on and off. + */ + +/* This structure enforces the header file is included only once in the build. + * Violating this requirement triggers a multiple definition error at link time. + */ +const struct {} port_state_def_include_once; + + +static const struct port_state port_state_on[] = { +}; + +static const struct port_state port_state_off[] = { +}; diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj.conf new file mode 100644 index 00000000000..0c57343de2f --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj.conf @@ -0,0 +1,112 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ +# Application Configuration + +CONFIG_DESKTOP_INIT_LOG_MOTION_EVENT=n +CONFIG_DESKTOP_INIT_LOG_HID_REPORT_EVENT=n +CONFIG_DESKTOP_INIT_LOG_HID_REPORT_SENT_EVENT=n +CONFIG_CAF_INIT_LOG_KEEP_ALIVE_EVENTS=n + +CONFIG_DESKTOP_ROLE_HID_PERIPHERAL=y +CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y +CONFIG_DESKTOP_DEVICE_PID=0x52DE +CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y + +CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y +CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 +CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 +CONFIG_DESKTOP_MOTION_BUTTONS_LEFT_KEY_ID=2 +CONFIG_DESKTOP_MOTION_BUTTONS_RIGHT_KEY_ID=1 + +CONFIG_CAF_BUTTONS=y +CONFIG_CAF_BUTTONS_POLARITY_INVERSED=y +CONFIG_CAF_BUTTONS_PM_KEEP_ALIVE=n + +CONFIG_CAF_CLICK_DETECTOR=y + +CONFIG_CAF_LEDS=y + +CONFIG_DESKTOP_BLE_USE_DEFAULT_ID=y + +CONFIG_DESKTOP_BLE_PEER_CONTROL=y +CONFIG_DESKTOP_BLE_PEER_CONTROL_BUTTON=0x0000 +CONFIG_DESKTOP_BLE_PEER_ERASE_ON_START=y + +CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 +CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y + +CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y +CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y + +################################################################################ +# Zephyr Configuration + +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536 +CONFIG_ISR_STACK_SIZE=1536 +CONFIG_MAIN_STACK_SIZE=840 +CONFIG_BT_RX_STACK_SIZE=2048 +CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y +CONFIG_BT_HCI_TX_STACK_SIZE=1536 + +CONFIG_BOOT_BANNER=n + +CONFIG_NUM_COOP_PRIORITIES=10 +CONFIG_NUM_PREEMPT_PRIORITIES=11 + +CONFIG_HEAP_MEM_POOL_SIZE=512 + +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_HW_STACK_PROTECTION=y +CONFIG_RESET_ON_FATAL_ERROR=n + +CONFIG_GPIO=y + +CONFIG_REBOOT=y + +CONFIG_SPEED_OPTIMIZATIONS=y + +CONFIG_LED=y +CONFIG_LED_GPIO=y + +CONFIG_BT_MAX_PAIRED=2 +CONFIG_BT_ID_MAX=3 + +CONFIG_BT_CTLR_SDC_LLPM=y +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y +CONFIG_BT_CONN_TX_MAX=4 + +################################################################################ + +CONFIG_ASSERT=y +CONFIG_ASSERT_LEVEL=2 + +# nRF54L PDK uses UART for logs. +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_LOG=y +CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_BACKEND_SHOW_COLOR=n +CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP=n +CONFIG_LOG_MODE_DEFERRED=y +CONFIG_LOG_PRINTK=y +CONFIG_LOG_BUFFER_SIZE=4096 +CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1024 + +################################################################################ +# Bootloader Configuration + +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUBOOT_IMG_MANAGER=y +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_keyboard.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_keyboard.conf new file mode 100644 index 00000000000..10f6166d7b1 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_keyboard.conf @@ -0,0 +1,117 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ +# ZDebug: Keyboard version +# +# This ZDebug build type configuration acts as a keyboard. +# +# Application Configuration + +CONFIG_DESKTOP_INIT_LOG_HID_REPORT_EVENT=n +CONFIG_DESKTOP_INIT_LOG_HID_REPORT_SENT_EVENT=n +CONFIG_CAF_INIT_LOG_KEEP_ALIVE_EVENTS=n + +CONFIG_DESKTOP_ROLE_HID_PERIPHERAL=y +CONFIG_DESKTOP_PERIPHERAL_TYPE_KEYBOARD=y +CONFIG_DESKTOP_DEVICE_PID=0x52DD +CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD=y +CONFIG_DESKTOP_HID_STATE_HID_KEYMAP_DEF_PATH="hid_keymap_def_keyboard.h" +CONFIG_DESKTOP_HID_STATE_HID_KEYBOARD_LEDS_DEF_PATH="hid_keyboard_leds_def_keyboard.h" +CONFIG_DESKTOP_HID_REPORT_EXPIRATION=10000 +CONFIG_DESKTOP_HID_EVENT_QUEUE_SIZE=60 + +CONFIG_CAF_BUTTONS=y +CONFIG_CAF_BUTTONS_POLARITY_INVERSED=y +CONFIG_CAF_BUTTONS_PM_KEEP_ALIVE=n + +CONFIG_CAF_CLICK_DETECTOR=y + +CONFIG_CAF_LEDS=y + +CONFIG_DESKTOP_BUTTONS_SIM_ENABLE=y +CONFIG_DESKTOP_BUTTONS_SIM_INTERVAL=100 +CONFIG_DESKTOP_BUTTONS_SIM_LOOP_FOREVER=y +CONFIG_DESKTOP_BUTTONS_SIM_TRIGGER_KEY_ID=0x03 + +CONFIG_DESKTOP_BLE_PEER_CONTROL=y +CONFIG_DESKTOP_BLE_PEER_CONTROL_BUTTON=0x0000 +CONFIG_DESKTOP_BLE_PEER_ERASE_ON_START=y + +CONFIG_DESKTOP_BLE_USE_DEFAULT_ID=y + +CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 +CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y + +CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y +CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y + +################################################################################ +# Zephyr Configuration + +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536 +CONFIG_ISR_STACK_SIZE=1536 +CONFIG_MAIN_STACK_SIZE=840 +CONFIG_BT_RX_STACK_SIZE=2048 +CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y +CONFIG_BT_HCI_TX_STACK_SIZE=1536 + +CONFIG_BOOT_BANNER=n + +CONFIG_NUM_COOP_PRIORITIES=10 +CONFIG_NUM_PREEMPT_PRIORITIES=11 + +CONFIG_HEAP_MEM_POOL_SIZE=4096 + +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_HW_STACK_PROTECTION=y +CONFIG_RESET_ON_FATAL_ERROR=n + +CONFIG_GPIO=y +CONFIG_REBOOT=y + +CONFIG_SPEED_OPTIMIZATIONS=y + +CONFIG_LED=y +CONFIG_LED_GPIO=y + +CONFIG_BT_MAX_PAIRED=2 +CONFIG_BT_ID_MAX=3 + +CONFIG_BT_CTLR_SDC_LLPM=y +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y +CONFIG_BT_CONN_TX_MAX=6 + +################################################################################ + +CONFIG_ASSERT=y +CONFIG_ASSERT_LEVEL=2 + +# nRF54L PDK uses UART for logs. +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_LOG=y +CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_BACKEND_SHOW_COLOR=n +CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP=n +CONFIG_LOG_MODE_DEFERRED=y +CONFIG_LOG_PRINTK=y +CONFIG_LOG_BUFFER_SIZE=4096 +CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1024 + +################################################################################ +# Bootloader Configuration + +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUBOOT_IMG_MANAGER=y +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n diff --git a/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_release.conf b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_release.conf new file mode 100644 index 00000000000..9f16f0b7378 --- /dev/null +++ b/applications/nrf_desktop/configuration/nrf54l15pdk_nrf54l15_cpuapp/prj_release.conf @@ -0,0 +1,94 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +################################################################################ +# Application Configuration + +CONFIG_DESKTOP_ROLE_HID_PERIPHERAL=y +CONFIG_DESKTOP_PERIPHERAL_TYPE_MOUSE=y +CONFIG_DESKTOP_DEVICE_PID=0x52DE +CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE=y + +CONFIG_DESKTOP_MOTION_BUTTONS_ENABLE=y +CONFIG_DESKTOP_MOTION_BUTTONS_UP_KEY_ID=0 +CONFIG_DESKTOP_MOTION_BUTTONS_DOWN_KEY_ID=3 +CONFIG_DESKTOP_MOTION_BUTTONS_LEFT_KEY_ID=2 +CONFIG_DESKTOP_MOTION_BUTTONS_RIGHT_KEY_ID=1 + +CONFIG_CAF_BUTTONS=y +CONFIG_CAF_BUTTONS_POLARITY_INVERSED=y +CONFIG_CAF_BUTTONS_PM_KEEP_ALIVE=n + +CONFIG_CAF_CLICK_DETECTOR=y + +CONFIG_CAF_LEDS=y + +CONFIG_DESKTOP_BLE_PEER_CONTROL=y +CONFIG_DESKTOP_BLE_PEER_CONTROL_BUTTON=0x0000 +CONFIG_DESKTOP_BLE_PEER_ERASE_ON_START=y + +CONFIG_DESKTOP_BLE_SECURITY_FAIL_TIMEOUT_S=10 +CONFIG_DESKTOP_BLE_LOW_LATENCY_LOCK=y + +CONFIG_DESKTOP_WATCHDOG_ENABLE=y +CONFIG_DESKTOP_FAILSAFE_ENABLE=y + +CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE=y +CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT=y +CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_ENABLE=y + +################################################################################ +# Zephyr Configuration + +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536 +CONFIG_ISR_STACK_SIZE=1536 +CONFIG_MAIN_STACK_SIZE=840 +CONFIG_BT_RX_STACK_SIZE=2048 +CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y +CONFIG_BT_HCI_TX_STACK_SIZE=1536 + +CONFIG_BOOT_BANNER=n + +CONFIG_NUM_COOP_PRIORITIES=10 +CONFIG_NUM_PREEMPT_PRIORITIES=11 + +CONFIG_HEAP_MEM_POOL_SIZE=512 + +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_SYSTEM_CLOCK_NO_WAIT=y + +CONFIG_HW_STACK_PROTECTION=n +CONFIG_RESET_ON_FATAL_ERROR=n + +CONFIG_GPIO=y + +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n + +CONFIG_REBOOT=y + +CONFIG_SPEED_OPTIMIZATIONS=y + +CONFIG_LED=y +CONFIG_LED_GPIO=y + +CONFIG_BT_MAX_PAIRED=2 +CONFIG_BT_ID_MAX=3 + +CONFIG_BT_CTLR_SDC_LLPM=y +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y +CONFIG_BT_CONN_TX_MAX=4 + +################################################################################ +# Bootloader Configuration + +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP=y +CONFIG_STREAM_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUBOOT_IMG_MANAGER=y +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n diff --git a/applications/nrf_desktop/configuration_options.rst b/applications/nrf_desktop/configuration_options.rst new file mode 100644 index 00000000000..55921c4b996 --- /dev/null +++ b/applications/nrf_desktop/configuration_options.rst @@ -0,0 +1,13 @@ +.. _config_desktop_app_options: + +nRF Desktop: Application Kconfig options scheme +############################################### + +.. contents:: + :local: + :depth: 2 + +Following are the application-specific configuration options that can be configured for the nRF desktop and the internal modules: + +.. options-from-kconfig:: + :show-type: diff --git a/applications/nrf_desktop/description.rst b/applications/nrf_desktop/description.rst new file mode 100644 index 00000000000..fc8ad2913a2 --- /dev/null +++ b/applications/nrf_desktop/description.rst @@ -0,0 +1,1086 @@ +.. _nrf_desktop_description: + +nRF Desktop: Application description +#################################### + +.. contents:: + :local: + :depth: 2 + +The nRF Desktop application supports common input hardware interfaces like motion sensors, rotation sensors, and buttons martixes. +You can configure the firmware at runtime using a dedicated configuration channel established with the HID feature report. +The same channel is used to transmit DFU packets. + +The fwupd tools can communicate with devices running the nRF Desktop application with the :ref:`nrf_desktop_bootloader_background_dfu` feature enabled. +For more information on fwupd support in the nRF desktop application, see the :ref:`nrf_desktop_fwupd` page. + +.. _nrf_desktop_architecture: + +Application overview +******************** + +The nRF Desktop application design aims at high performance, while still providing configurability and extensibility. + +The application architecture is modular, event-driven and build around :ref:`lib_caf`. +This means that parts of the application functionality are separated into isolated modules that communicate with each other using application events that are handled by the :ref:`app_event_manager`. +Modules register themselves as listeners of events that they are configured to react to. +An application event can be submitted by multiple modules and it can have multiple listeners. + +.. _nrf_desktop_module_component: + +Module and component overview +============================= + +The following figure shows the nRF Desktop modules and how they relate to other components and the :ref:`app_event_manager`. +The figure does not present all the available modules. +For example, the figure does not include the modules that are used as hotfixes or only for debug or profiling purposes. + +.. figure:: /images/nrf_desktop_arch.svg + :alt: nRF Desktop high-level design (overview) + + Application high-level design overview + +For more information about nRF Desktop modules, see the :ref:`nrf_desktop_app_internal_modules` section. + +.. _nrf_desktop_module_table: + +Module event tables +------------------- + +The :ref:`documentation page of each application module ` includes a table that shows the event-based communication for the module. + ++---------------------------------------+-------------+------------------------------------+--------------+-----------------------------------------+ +| Source module | Input event | This module | Output event | Sink module | ++=======================================+=============+====================================+==============+=========================================+ +| The module that submits ``eventA``. | ``eventA`` | The module described by the table. | | | ++---------------------------------------+ | | | | +| Other module that submits ``eventA``. | | | | | ++---------------------------------------+-------------+ +--------------+-----------------------------------------+ +| The module that submits ``eventB``. | ``eventB`` | | | | ++---------------------------------------+-------------+ +--------------+-----------------------------------------+ +| | | | ``eventC`` | The module that reacts on ``eventC``. | ++---------------------------------------+-------------+------------------------------------+--------------+-----------------------------------------+ + +Each module event table contains the following columns: + +Source module + The module that submits a given application event. + Some of these events can have many listeners or sources. + These are listed on the :ref:`nrf_desktop_event_rel_modules` page. + +Input event + An application event that is received by the module described in the table. + +This module + The module described in the table. + This is the module that is the target of the input events and the source of output events directed to the sink modules. + +Output event + An application event that is submitted by the module described in the table. + +Sink module + The module that reacts on an application event. + Some of these events can have many listeners or sources. + These are listed on the :ref:`nrf_desktop_event_rel_modules` page. + +.. note:: + Some application modules can have multiple implementations (for example, :ref:`nrf_desktop_motion`). + In such case, the table shows the :ref:`app_event_manager` events received and submitted by all implementations of a given application module. + +Module usage per hardware type +============================== + +Since the application architecture is uniform and the code is shared, the set of modules in use depends on the selected device role. +A different set of modules is enabled when the application is working as a mouse, keyboard, or dongle. +In other words, not all of the :ref:`nrf_desktop_app_internal_modules` need to be enabled for a given reference design. + +Gaming mouse module set +----------------------- + +The following figure shows the modules that are enabled when the application is working as a gaming mouse: + +.. figure:: /images/nrf_desktop_arch_gmouse.svg + :alt: nRF Desktop high-level design (gaming mouse) + + Application configured as a gaming mouse + +Desktop mouse module set +------------------------ + +The following figure shows the modules that are enabled when the application is working as a desktop mouse: + +.. figure:: /images/nrf_desktop_arch_dmouse.svg + :alt: nRF Desktop high-level design (desktop mouse) + + Application configured as a desktop mouse + +Keyboard module set +------------------- + +The following figure shows the modules that are enabled when the application is working as a keyboard: + +.. figure:: /images/nrf_desktop_arch_kbd.svg + :alt: nRF Desktop high-level design (keyboard) + + Application configured as a keyboard + +Dongle module set +----------------- + +The following figure shows the modules that are enabled when the application is working as a dongle: + +.. figure:: /images/nrf_desktop_arch_dongle.svg + :alt: nRF Desktop high-level design (dongle) + + Application configured as a dongle + +Thread usage +============ + +The application limits the number of threads in use to the minimum and does not use the user-space threads. + +The following threads are kept running in the application: + +* System-related threads + * Idle thread + * System workqueue thread + * Logger thread (when :ref:`zephyr:logging_api` is enabled) + * Shell thread (when :ref:`zephyr:shell_api` is enabled) + * Threads related to *Bluetooth®* LE (the exact number depends on the selected Link Layer) +* Application-related threads + * Motion sensor thread (running only on mouse) + * Settings loading thread (enabled by default only on keyboard) + * QoS data sampling thread (running only if Bluetooth LE QoS feature is enabled) + +Most of the application activity takes place in the context of the system work queue thread, either through scheduled work objects or through the Application Event Manager callbacks (executed from the system workqueue thread). +Because of this, the application does not need to handle resource protection. +The only exception are places where the interaction with interrupts or multiple threads cannot be avoided. + +Memory allocation +================= + +Most of memory resources that are used by the application are allocated statically. + +The application uses dynamic allocation to: + +* Create the Application Event Manager events. + For more information, see the :ref:`app_event_manager` page. +* Temporarily store the HID-related data in the :ref:`nrf_desktop_hid_state` and :ref:`nrf_desktop_hid_forward`. + For more information, see the documentation pages of these modules. + +When configuring heap, make sure that the values for the following options match the typical event size and the system needs: + +* :kconfig:option:`CONFIG_HEAP_MEM_POOL_SIZE` - The size must be big enough to handle the worst possible use case for the given device. + +.. important:: + The nRF Desktop uses ``k_heap`` as the backend for dynamic allocation. + This backend is used by default in Zephyr. + For more information, refer to Zephyr's documentation about :ref:`zephyr:heap_v2`. + +HID data handling +================= + +The nRF Desktop device and the host can exchange HID data using one of the following HID report types: + +* HID input report +* HID output report +* HID feature report + +The nRF Desktop application uses all of these report types. +See sections below for details about handling given HID report type. + +HID input reports +----------------- + +The nRF Desktop application uses HID input reports to transmit information about user input from the nRF Desktop device to a host. +The user input can be, for example, button press or mouse motion. + +The nRF Desktop supports the following HID input reports: + +* HID mouse report +* HID keyboard report +* HID consumer control report +* HID system control report + +All of these reports use predefined report format and provide the given information. +For example, the mouse motion is forwarded as HID mouse report. + +An nRF Desktop device supports the selected subset of the HID input reports. +For example, the nRF Desktop keyboard reference design (``nrf52kbd_nrf52832``) supports HID keyboard report, HID consumer control report and HID system control report. + +As an example, the following section describes handling HID mouse report data. + +HID mouse report handling +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The nRF Desktop mouse sends HID input reports to the host after the host connects and subscribes for the HID reports. + +The :ref:`nrf_desktop_motion` sensor sampling is synchronized with sending the HID mouse input reports to the host. + +The :ref:`nrf_desktop_wheel` and :ref:`caf_buttons` provide data to the :ref:`nrf_desktop_hid_state` when the mouse wheel is used or a button is pressed, respectively. +These inputs are not synchronized with the HID report transmission to the host. + +When the mouse is constantly in use, the motion module is kept in the fetching state. +In this state, the nRF Desktop mouse forwards the data from the motion sensor to the host in the following way: + +1. USB state (or Bluetooth HIDS) sends a HID mouse report to the host and submits ``hid_report_sent_event``. +#. The event triggers sampling of the motion sensor. +#. A dedicated thread is used to fetch the sample from the sensor. +#. After the sample is fetched, the thread forwards it to the :ref:`nrf_desktop_hid_state` as ``motion_event``. +#. The |hid_state| updates the HID report data, generates new HID input report, and submits it as ``hid_report_event``. +#. The HID report data is forwarded to the host either by the :ref:`nrf_desktop_usb_state` or by the :ref:`nrf_desktop_hids`. + The USB state has precedence if the USB is connected. +#. When the HID input report is sent to the host, ``hid_report_sent_event`` is submitted. + The motion sensor sample is triggered and the sequence repeats. + +If the device is connected through Bluetooth, the :ref:`nrf_desktop_hid_state` uses a pipeline that consists of two HID reports that it creates upon receiving the first ``motion_event``. +The |hid_state| submits two ``hid_report_event`` events. +Sending the first event to the host triggers the motion sensor sample. + +For the Bluetooth connections, submitting ``hid_report_sent_event`` is delayed by one Bluetooth connection interval. +Because of this delay, the :ref:`nrf_desktop_hids` requires a pipeline of two HID reports to make sure that data is sent on every connection event. +Such solution is necessary to achieve high report rate. + +If there is no motion data for the predefined number of samples, the :ref:`nrf_desktop_motion` goes to the idle state. +This is done to reduce the power consumption. +When a motion is detected, the module switches back to the fetching state. + +The following diagram shows the data exchange between the application modules. +To keep it simple, the diagram only shows data related to HID input reports that are sent after the host is connected and the HID subscriptions are enabled. + +.. figure:: /images/nrf_desktop_motion_sensing.svg + :alt: nRF Desktop mouse HID data sensing and transmission + + nRF Desktop mouse HID data sensing and transmission + +HID output reports +------------------ + +HID output reports are used to transmit data from host to an nRF Desktop device. +The nRF Desktop supports the HID keyboard LED report. +The report is used by the host to update the state of the keyboard LEDs, for example to indicate that the Caps Lock key is active. + +.. note:: + Only the ``nrf52840dk_nrf52840`` in ``keyboard`` configuration has hardware LEDs that can be used to display the Caps Lock and Num Lock state. + +The following diagrams show the HID output report data exchange between the application modules. + +* Scenario 1: Peripheral connected directly to the host + + .. figure:: /images/nrf_desktop_peripheral_host.svg + :alt: HID output report: Data handling and transmission between host and peripheral + + HID output report: Data handling and transmission between host and peripheral + + In this scenario, the HID output report is sent from the host to the peripheral either through Bluetooth or the USB connection. + Depending on the connection, the HID report is received by the :ref:`nrf_desktop_hids` or :ref:`nrf_desktop_usb_state`, respectively. + The module then sends the HID output report as ``hid_report_event`` to the :ref:`nrf_desktop_hid_state` that keeps track of the HID output report states and updates state of the hardware LEDs by sending ``led_event`` to :ref:`nrf_desktop_leds`. + +* Scenario 2: Dongle intermediates between the host and the peripheral + + .. figure:: /images/nrf_desktop_peripheral_host_dongle.svg + :alt: HID output report: Data handling and transmission between host and peripheral through dongle + + HID output report: Data handling and transmission between host and peripheral through dongle + + In this scenario, the HID output report is sent from the host to the dongle using the USB connection and is received by the :ref:`nrf_desktop_usb_state`. + The destination module then sends the HID output report as ``hid_report_event`` to the :ref:`nrf_desktop_hid_forward` that sends it to the peripheral using Bluetooth. + +HID feature reports +------------------- + +HID feature reports are used to transmit data between the host and an nRF Desktop device (in both directions). +The nRF Desktop uses only one HID feature report: the user config report. +The report is used by the :ref:`nrf_desktop_config_channel`. + +.. note:: + The nRF Desktop also uses a dedicated HID output report to forward the :ref:`nrf_desktop_config_channel` data through the nRF Desktop dongle. + This report is handled using the configuration channel's infrastructure and you can enable it using the :ref:`CONFIG_DESKTOP_CONFIG_CHANNEL_OUT_REPORT ` Kconfig option. + See the Kconfig option's help for details about the report. + +HID protocols +------------- + +The following HID protocols are supported by nRF Desktop for HID input and output reports: + +* Report protocol - Most widely used in HID devices. + When establishing a connection, the host reads a HID descriptor from the HID device. + The HID descriptor describes the format of HID reports and is used by the host to interpret the data exchanged between the HID device and the host. +* Boot protocol - Only available for mice and keyboards data. + No HID descriptor is used for this HID protocol. + Instead, fixed data packet formats must be used to send data between the HID device and the host. + +.. _nrf_desktop_requirements: + +Requirements +************ + +The nRF Desktop application supports several development kits related to the following hardware reference designs. +Depending on the development kit you use, you need to select the respective configuration file and :ref:`build type `. + +.. tabs:: + + .. tab:: Gaming mouse + + .. figure:: /images/nrf_desktop_gaming_mouse_top_no_captions.svg + :alt: nRF Desktop gaming mouse (top view) + + .. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf52840gmouse_nrf52840 + + .. tab:: Desktop mouse + + .. figure:: /images/nrf_desktop_desktop_mouse_side_no_captions.svg + :alt: nRF Desktop desktop mouse (side view) + + .. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf52dmouse_nrf52832, nrf52810dmouse_nrf52810 + + .. tab:: Keyboard + + .. figure:: /images/nrf_desktop_keyboard_top_no_captions.svg + :alt: nRF Desktop keyboard (top view) + + .. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf52kbd_nrf52832 + + .. tab:: HID dongle + + .. figure:: /images/nrf_desktop_dongle_no_captions.svg + :alt: nRF Desktop dongle (top view) + + .. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf52840dongle_nrf52840, nrf52833dongle_nrf52833, nrf52820dongle_nrf52820 + + .. tab:: DK + + .. figure:: /images/nrf_desktop_nrf52840_dk_no_captions.svg + :alt: DK + + .. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf52840dk_nrf52840, nrf52833dk_nrf52833, nrf52833dk_nrf52820, nrf5340dk_nrf5340_cpuapp, nrf54l15pdk_nrf54l15_cpuapp + + Depending on the configuration, a DK may act either as mouse, keyboard or dongle. + For information about supported configurations for each board, see the :ref:`nrf_desktop_board_configuration_files` section. + +.. + +The application is designed to allow easy porting to new hardware. +See :ref:`nrf_desktop_porting_guide` for details. + +.. _nrf_desktop_requirements_build_types: + +nRF Desktop build types +======================= + +The nRF Desktop application does not use a single :file:`prj.conf` file. +Before you start testing the application, you can select one of the build types supported by the application. +Not every board supports all of the mentioned build types. + +See :ref:`app_build_additions_build_types` and :ref:`cmake_options` for more information. + +The application supports the following build types: + +.. list-table:: nRF Desktop build types + :widths: auto + :header-rows: 1 + + * - Build type + - File name + - Supported board + - Description + * - Debug (default) + - :file:`prj.conf` + - All from `Requirements`_ + - Debug version of the application; the same as the ``release`` build type, but with debug options enabled. + * - Release + - :file:`prj_release.conf` + - All from `Requirements`_ + - Release version of the application with no debugging features. + * - Debug Fast Pair + - :file:`prj_fast_pair.conf` + - ``nrf52840dk_nrf52840``, ``nrf52840gmouse_nrf52840`` + - Debug version of the application with `Fast Pair`_ support. + * - Release Fast Pair + - :file:`prj_release_fast_pair.conf` + - ``nrf52kbd_nrf52832``, ``nrf52840gmouse_nrf52840`` + - Release version of the application with `Fast Pair`_ support. + * - Dongle + - :file:`prj_dongle.conf` + - ``nrf52840dk_nrf52840`` + - Debug version of the application that lets you generate the application with the dongle role. + * - Keyboard + - :file:`prj_keyboard.conf` + - ``nrf52840dk_nrf52840`` + - Debug version of the application that lets you generate the application with the keyboard role. + * - MCUboot QSPI + - :file:`prj_mcuboot_qspi.conf` + - ``nrf52840dk_nrf52840`` + - Debug version of the application that uses MCUboot with the secondary slot in the external QSPI FLASH. + * - MCUboot SMP + - :file:`prj_mcuboot_smp.conf` + - ``nrf52840dk_nrf52840``, ``nrf52840gmouse_nrf52840`` + - | Debug version of the application that enables MCUmgr with DFU support and offers support for the MCUboot DFU procedure over SMP. + | See the :ref:`nrf_desktop_bootloader_background_dfu` section for more information. + * - WWCB + - :file:`prj_wwcb.conf` + - ``nrf52840dk_nrf52840`` + - Debug version of the application with the support for the B0 bootloader enabled for `Works With ChromeBook (WWCB)`_. + * - Triple Bluetooth LE connection + - :file:`prj_3bleconn.conf` + - ``nrf52840dongle_nrf52840`` + - Debug version of the application with the support for up to three simultaneous Bluetooth LE connections. + * - Quadruple LLPM connection + - :file:`prj_4llpmconn.conf` + - ``nrf52840dongle_nrf52840`` + - Debug version of the application with the support for up to four simultaneous Bluetooth LE connections, in Low Latency Packet Mode. + * - Release quadruple LLPM connection + - :file:`prj_release_4llpmconn.conf` + - ``nrf52840dongle_nrf52840`` + - Release version of the application with the support for up to four simultaneous Bluetooth LE connections, in Low Latency Packet Mode. + +.. note:: + Bootloader-enabled configurations with support for :ref:`serial recovery DFU ` or :ref:`background DFU ` are set as default if they fit in the non-volatile memory. + See :ref:`nrf_desktop_board_configuration_files` for details about which boards have bootloader included in their default configuration. + +See :ref:`nrf_desktop_porting_guide` for detailed information about the application configuration and how to create build type files for your hardware. + +.. _nrf_desktop_user_interface: + +User interface +************** + +The nRF Desktop configuration files have a set of preprogrammed options bound to different parts of the hardware. +These options are related to the functionalities discussed in this section. + +Turning devices on and off +========================== + +The nRF Desktop hardware reference designs are equipped with hardware switches to turn the device on and off. +See the following figures for the exact location of these switches: + +.. tabs:: + + .. tab:: Gaming mouse + + .. figure:: /images/nrf_desktop_gaming_mouse_bottom.svg + :alt: nRF Desktop gaming mouse (bottom view) + + The switch is located at the bottom of the gaming mouse, close to the optical sensor. + The mouse uses this switch also for changing dongle and Bluetooth LE peers, as described in the `Bluetooth LE peer control`_ section. + + .. tab:: Desktop mouse + + .. figure:: /images/nrf_desktop_desktop_mouse_bottom.svg + :alt: nRF Desktop desktop mouse (bottom view) + + The switch is located at the bottom of the desktop mouse, close to the optical sensor. + + .. tab:: Keyboard + + .. figure:: /images/nrf_desktop_keyboard_back_power.svg + :alt: nRF Desktop keyboard (back view) + + The switch is located at the back of the keyboard. + +.. + +Connectability +============== + +The nRF Desktop devices provide user input to the host in the same way as other mice and keyboards, using connection through USB or Bluetooth LE. + +The nRF Desktop devices support additional operations, like firmware upgrade or configuration change. +The support is implemented through the :ref:`nrf_desktop_config_channel`. +The host can use dedicated Python scripts to exchange the data with an nRF Desktop peripheral. +For detailed information, see :ref:`nrf_desktop_config_channel_script`. + +The behavior of a device can change due to power saving measures. +For more information, see the `Power management`_ section. + +.. _nrf_desktop_usb: + +Connection through USB +---------------------- + +The nRF Desktop devices use the USB HID class. +No additional software or drivers are required. + +.. tabs:: + + .. tab:: Gaming mouse + + .. figure:: /images/nrf_desktop_gaming_mouse_usb_slot.svg + :alt: nRF Desktop gaming mouse (top view) + + The gaming mouse has the USB connector slot located below the scroll wheel. + The connector should slide in the socket along the cut in the mouse base. + + .. tab:: HID dongle + + .. figure:: /images/nrf_desktop_dongle_usb.svg + :alt: nRF Desktop dongle + + The dongle has a USB connector located at one end of the board. + It should be inserted to the USB slot located on the host. + +.. + +Gaming mouse, dongle, and DK support the HID data transmission through USB. + +Gaming mouse USB +~~~~~~~~~~~~~~~~ + +The gaming mouse can send HID data when connected through USB. +When the device is connected both wirelessly and through USB at the same time, it provides input only through the USB connection. +If the device is disconnected from USB, it automatically switches to sending the data wirelessly using Bluetooth LE. + +The gaming mouse is a battery-powered device. +When it is connected through USB, charging of the rechargeable batteries starts. + +Dongle USB +~~~~~~~~~~ + +The nRF Desktop dongle works as a bridge between the devices connected through standard Bluetooth LE or Low Latency Packet Mode and the host connected through USB. +It receives data wirelessly from the connected peripherals and forwards the data to the host. + +The nRF Desktop dongle is powered directly through USB. + +DK USB +~~~~~~ + +The DK functionality depends on the application configuration. +Depending on the selected configuration options, it can work as a mouse, keyboard, or a dongle. + +.. _nrf_desktop_ble: + +Connection through Bluetooth LE +------------------------------- + +When turned on, the nRF Desktop peripherals are advertising until they go to the suspended state or connect through Bluetooth. +The peripheral supports one wireless connection at a time, but it can be bonded with :ref:`multiple peers `. + +.. note:: + To simplify pairing the nRF Desktop peripherals with Windows 10 hosts, the peripherals include `Swift Pair`_ payload in the Bluetooth LE advertising data. + By default, the Swift Pair payload is included for all of the Bluetooth local identities, apart from the dedicated local identity used for connection with an nRF Desktop dongle. + + Some of the nRF Desktop configurations also include `Fast Pair`_ payload in the Bluetooth LE advertising data to simplify pairing the nRF Desktop peripherals with Android hosts. + These configurations apply further modifications that are needed to improve the user experience. + See the :ref:`nrf_desktop_bluetooth_guide_fast_pair` section for details. + +The nRF Desktop Bluetooth Central device scans for all bonded peripherals that are not connected. +Right after entering the scanning state, the scanning operation is uninterruptible for a predefined time (:kconfig:option:`CONFIG_DESKTOP_BLE_FORCED_SCAN_DURATION_S`) to speed up connection establishment with Bluetooth Peripherals. +After the timeout, the scanning is interrupted when any device connected to the dongle through Bluetooth becomes active. +A connected peripheral is considered active when it provides HID input reports. +Continuing the scanning in such scenario would cause report rate drop. + +The scanning starts automatically when one of the bonded peers disconnects. +It also takes place periodically when a known peer is not connected. + +The peripheral connection can be based on standard Bluetooth LE connection parameters or on Bluetooth LE with Low Latency Packet Mode (LLPM). + +LLPM is a proprietary Bluetooth extension from Nordic Semiconductor. +It can be used only if it is supported by both connected devices (desktop mice do not support it). +LLPM enables sending data with high report rate (up to 1000 reports per second), which is not supported by the standard Bluetooth LE. + +.. _nrf_desktop_ble_peers: + +Bluetooth LE peer control +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A connected Bluetooth LE peer device can be controlled using predefined buttons or button combinations. +There are several peer operations available. + +The application distinguishes between the following button press types: + +* Short - Button pressed for less than 0.5 seconds. +* Standard - Button pressed for more than 0.5 seconds, but less than 5 seconds. +* Long - Button pressed for more than 5 seconds. +* Double - Button pressed twice in quick succession. + +The peer operation states provide visual feedback through LEDs (if the device has LEDs). +Each of the states is represented by separate LED color and effect. +The LED colors and effects are described in the :file:`led_state_def.h` file located in the board-specific directory in the application configuration directory. + +The assignments of hardware interface elements depend on the device type. + +.. tabs:: + + .. tab:: Gaming mouse + + The following predefined hardware interface elements are assigned to peer control operations for the gaming mouse: + + Hardware switch + * The switch is located next to the optical sensor. + + .. figure:: /images/nrf_desktop_gaming_mouse_bottom.svg + :alt: nRF Desktop gaming mouse - bottom view + + nRF Desktop gaming mouse - bottom view + + * You can set the switch in the following positions: + + * Top position: Select the dongle peer. + * Middle position: Select the Bluetooth LE peers. + * Bottom position: Mouse turned off. + + When the dongle peer is selected, the peer control is disabled until the switch is set to another position. + + Peer control button + * The button is located on the left side of the mouse, in the thumb area. + + .. figure:: /images/nrf_desktop_gaming_mouse_led1_peer_control_button.svg + :alt: nRF Desktop gaming mouse - side view + + nRF Desktop gaming mouse - side view + + * Short-press to initialize the peer selection. + (The **LED1** changes color and starts blinking.) + During the peer selection: + + 1. Short-press to toggle between available peers. + The **LED1** changes color for each peer and keeps blinking. + #. Double-press to confirm the peer selection. + The peer is changed after the confirmation. + **LED1** stops blinking. + + .. note:: + |led_note| + + * Long-press to initialize the peer erase. + When **LED1** starts blinking rapidly, double-press to confirm the operation. + |nRF_Desktop_confirmation_effect| + * |nRF_Desktop_cancel_operation| + + .. tab:: Desktop mouse + + The following predefined buttons are assigned to peer control operations for the desktop mouse: + + Scroll wheel button + * Press the scroll wheel before the mouse is powered up with the on/off switch. + Long-press to initialize and confirm the peer erase. + + .. figure:: /images/nrf_desktop_desktop_mouse_side_scroll.svg + :alt: nRF Desktop desktop mouse - side view + + nRF Desktop desktop mouse - side view + + |nRF_Desktop_confirmation_effect| + * |nRF_Desktop_cancel_operation| + + .. tab:: Keyboard + + The following predefined buttons or button combinations are assigned to peer control operations for the keyboard: + + Page Down key + * Press the Page Down key while keeping the Fn modifier key pressed. + + .. figure:: /images/nrf_desktop_keyboard_top.svg + :alt: nRF Desktop keyboard - top view + + nRF Desktop keyboard - top view + + * Short-press the Page Down key to initialize the peer selection. + During the peer selection: + + 1. Short-press to toggle between available peers. + **LED1** blinks rapidly for each peer. + The amount of blinks corresponds to the number assigned to a peer: one blink for peer 1, two blinks for peer 2, and so on. + #. Double-press to confirm the peer selection. + The peer is changed after the confirmation. + **LED1** becomes solid for a short time and then turns itself off. + + .. note:: + |led_note| + + * Long-press to initialize the peer erase. + When **LED1** starts blinking rapidly, double-press to confirm the operation. + |nRF_Desktop_confirmation_effect| + * |nRF_Desktop_cancel_operation| + + .. tab:: HID dongle + + The following predefined buttons are assigned to peer control operations for the HID dongle: + + SW1 button + * The **SW1** button is located on the top of the dongle, on the same side as **LED2**. + + .. figure:: /images/nrf_desktop_dongle_front_led2_sw1.svg + :alt: nRF Desktop dongle - top view + + nRF Desktop dongle - top view + + * Long-press to initialize peer erase. + When **LED2** starts blinking rapidly, double-press to confirm the operation. + After the confirmation, all the Bluetooth bonds are removed for the dongle. + * Short-press to start scanning for both bonded and non-bonded Bluetooth Peripherals. + After the forced scan timeout, the scan is interrupted if another peripheral connected to the dongle is active. + + .. note:: + |led_note| + + * |nRF_Desktop_cancel_operation| + +.. + +System state indication +======================= + +When available, one of the LEDs is used to indicate the state of the device. +This system state LED is kept lit when the device is active. + +.. tabs:: + + .. tab:: Gaming mouse + + .. figure:: /images/nrf_desktop_gaming_mouse_led2.svg + :alt: nRF Desktop gaming mouse (top view) + + The system state LED of the gaming mouse is located under the transparent section of the cover. + The color of the LED changes when the device's battery is being charged. + + .. tab:: HID dongle + + .. figure:: /images/nrf_desktop_dongle_front_led1.svg + :alt: nRF Desktop dongle + + **LED1** is used for the system state indication. + It is located in the bottom right corner of the dongle, next to the USB connector. + +.. + +In case of a system error, the system state LED will start to blink rapidly for some time before the device is reset. + +.. _nrf_desktop_debugging: + +Debugging +========= + +Each of the nRF Desktop hardware reference designs has a slot for a dedicated debug board. +See the following figures for the exact location of these slots. + +.. tabs:: + + .. tab:: Gaming mouse + + .. figure:: /images/nrf_desktop_gaming_mouse_debug_board_slot.svg + :alt: nRF Desktop gaming mouse (top view) + + The debug slot is located at the end of the gaming mouse, below the cover. + + .. tab:: Desktop mouse + + .. figure:: /images/nrf_desktop_desktop_mouse_side_debug.svg + :alt: nRF Desktop desktop mouse (side view) + + The debug slot is located on the side of the desktop mouse. + It is accesible through a hole in the casing. + + .. tab:: Keyboard + + .. figure:: /images/nrf_desktop_keyboard_back_debug.svg + :alt: nRF Desktop keyboard (back view) + + The debug slot is located on the back of the keyboard. + +.. + +The boards that you can plug into these slots are shown below. +You can use the debug board for programming the device (and powering it). +The bypass boards are needed to make the device work when the debug board is not used. +Their purpose is to close the circuits, which allows the device to be powered, for example during :ref:`nrf_desktop_testing_steps`. + +.. tabs:: + + .. tab:: Debug board + + .. figure:: /images/nrf_desktop_400391_jlink_debug.svg + :alt: nRF Desktop debug board + + The device can be programmed using the J-Link. + The J-Link connector slot is located on the top of the debug board. + + .. tab:: Short bypass board + + .. figure:: /images/nrf_desktop_400398_debug.svg + :alt: nRF Desktop bypass board (short) + + The shorter nRF desktop bypass board can be used with the desktop mouse. + + .. tab:: Long bypass board + + .. figure:: /images/nrf_desktop_400398_long_debug.svg + :alt: nRF Desktop bypass board (long) + + The longer nRF desktop bypass board can be used with the gaming mouse. + +.. + +Power management +================ + +Reducing power consumption is important for every battery-powered device. + +The nRF Desktop peripherals are either suspended or powered off when they are not in use for a defined amount of time: + +* In the suspended state, the device maintains the active connection. +* In the powered off state, the CPU is switched to the off mode. + +In both cases, most of the functionalities are disabled. +For example, LEDs are turned off and advertising is stopped. + +Moving the mouse or pressing any button wakes up the device and turns on the disabled functionalities. + +You can define the amount of time after which the peripherals are suspended or powered off using the :kconfig:option:`CONFIG_CAF_POWER_MANAGER_TIMEOUT` Kconfig option. +By default, this period is set to 120 seconds. + +.. important:: + When the gaming mouse is powered from USB, the power down timeout functionality is disabled. + + If a nRF Desktop device supports remote wakeup, the USB connected device goes to suspended state when USB is suspended. + The device can then trigger remote wakeup of the connected host on user input. + +.. _nrf_desktop_configuration: + +Configuration +************* + +|config| + +This section also describes the configuration sources that are used for the default configuration. + +Configuration sources +===================== + +The nRF Desktop application uses the following files as configuration sources: + +* Devicetree Specification (DTS) files - These reflect the hardware configuration. + See :ref:`zephyr:dt-guide` for more information about the DTS data structure. +* :file:`_def` files - These contain configuration arrays for the application modules and are specific to the nRF Desktop application. +* Kconfig files - These reflect the software configuration. + See :ref:`kconfig_tips_and_tricks` for information about how to configure them. + +For information about differences between DTS and Kconfig, see :ref:`zephyr:dt_vs_kconfig`. + +The nRF Desktop introduces application-specific Kconfig options that can be used to simplify an application configuration. +For more information, see the :ref:`nrf_desktop_application_Kconfig` page. + +The nRF Desktop application can be used with various hardware boards. +For more information about board support in the application, see :ref:`nrf_desktop_board_configuration`. + +The nRF Desktop application can be used together with the `nRF21540 EK` shield to benefit from an RF front-end module (FEM) for the 2.4 GHz range extension. +For more information, see :ref:`nrf_desktop_nrf21540ek`. + +You can also configure the following feature in the nRF Desktop application: + +* :ref:`Memory layout ` +* :ref:`Bluetooth ` +* :ref:`Bootloader and Device Firmware Update ` + +Building and running +******************** + +.. |sample path| replace:: :file:`applications/nrf_desktop` + +The nRF Desktop application is built the same way to any other |NCS| application or sample. + +.. include:: /includes/build_and_run.txt + +.. note:: + Information about the known issues in nRF Desktop can be found in |NCS|'s :ref:`release_notes` and on the :ref:`known_issues` page. + +.. _nrf_desktop_selecting_build_types: + +Selecting a build type +====================== + +Before you start testing the application, you can select one of the :ref:`nrf_desktop_requirements_build_types`, depending on your development kit. +See :ref:`cmake_options` for information about how to select a build type. + +.. note:: + If nRF Desktop is built with `Fast Pair`_ support, you must provide Fast Pair Model ID and Anti Spoofing private key as CMake options. + You can use either your own provisioning data or the provisioning data obtained by Nordic Semiconductor for development purposes. + The following debug devices are meant to be used with the nRF Desktop and have been registered: + + * NCS keyboard - The Fast Pair Provider meant to be used with keyboards: + + * Device Name: NCS keyboard + * Model ID: ``0x52FF02`` + * Anti-Spoofing Private Key (base64, uncompressed): ``8E8ulwhSIp/skZeg27xmWv2SxRxTOagypHrf2OdrhGY=`` + * Device Type: Input Device + * Notification Type: Fast Pair + * Data-Only connection: true + * No Personalized Name: false + + * NCS gaming mouse - Fast Pair Provider meant to be used with gaming mice: + + * Device Name: NCS gaming mouse + * Model ID: ``0x8E717D`` + * Anti-Spoofing Private Key (base64, uncompressed): ``dZxFzP7X9CcfLPC0apyRkmgsh3n2EbWo9NFNXfVuxAM=`` + * Device Type: Input Device + * Notification Type: Fast Pair + * Data-Only connection: true + * No Personalized Name: false + + See :ref:`ug_bt_fast_pair_provisioning` documentation for the following information: + + * Registering a Fast Pair Provider + * Provisioning a Fast Pair Provider in |NCS| + +.. nrf_desktop_fastpair_important_start + +.. important:: + This is the debug Fast Pair provisioning data obtained by Nordic for the development purposes. + Do not use it in production. + + To test with the debug mode Model ID, you must configure the Android device to include the debug results while displaying the nearby Fast Pair Providers. + For details, see `Verifying Fast Pair`_ in the GFPS documentation. + +.. nrf_desktop_fastpair_important_end + +.. _nrf_desktop_testing_steps: + +Testing +======= + +You can build and test the application in various configurations. +The following procedure refers to the scenario where the gaming mouse (nRF52840 Gaming Mouse) and the keyboard (nRF52832 Desktop Keyboard) are connected simultaneously to the dongle (nRF52840 USB Dongle). + +After building the application with or without :ref:`specifying the build type `, test the nRF Desktop application by performing the following steps: + +1. Program the required firmware to each device. +#. Insert the :ref:`debug board or bypass board ` into the mouse to make sure it is powered. +#. Turn on both mouse and keyboard. + **LED1** on the keyboard and **LED1** on the mouse start breathing. +#. Plug the dongle to the USB port. + The blue **LED2** on the dongle starts breathing. + This indicates that the dongle is scanning for peripherals. +#. Wait for the establishment of the Bluetooth connection, which happens automatically. + After the Bluetooth connection is established, the LEDs stop breathing and remain turned on. + You can now use the devices simultaneously. + + .. note:: + You can manually start the scanning for new peripheral devices by pressing the **SW1** button on the dongle for a short time. + This might be needed if the dongle does not connect with all the peripherals before scanning is interrupted by a timeout. + +#. Move the mouse and press any key on the keyboard. + The input is reflected on the host. + + .. note:: + When a :ref:`configuration with debug features ` is enabled, for example logger and assertions, the gaming mouse report rate can be significantly lower. + + Make sure that you use the ``release``configurations before testing the mouse report rate. + For the ``release`` configurations, you should observe a 500-Hz report rate when both the mouse and the keyboard are connected and a 1000-Hz rate when only the mouse is connected. + +#. Switch the Bluetooth peer on the gaming mouse by pressing the **Precise Aim** button (see `User interface`_). + The color of **LED1** changes from red to green and the LED starts blinking rapidly. +#. Press the **Precise Aim** button twice quickly to confirm the selection. + After the confirmation, **LED1** starts breathing and the mouse starts the Bluetooth advertising. +#. Connect to the mouse with an Android phone, a laptop, or any other Bluetooth Central. + +After the connection is established and the device is bonded, you can use the mouse with the connected device. + +.. _nrf_desktop_measuring_hid_report_rate: + +Measuring HID report rate +------------------------- + +You can measure a HID report rate of your application to assess the performance of your HID device. +This measurement allows you to check how often the host computer can get user's input from the HID device. + +Prerequisites +~~~~~~~~~~~~~ + +The HID report rate can be measured by using either browser-based or platform-specific tools. +You can use any preferred HID report rate tool. + +.. note:: + The host computer controls polling a HID peripheral for HID reports. + The HID peripheral cannot trigger sending a HID report even if the report is prepared in time. + Polling inaccuracies and missing polls on the host side can negatively affect the measured report rate. + Make sure to close all unnecessary PC applications to mitigate negative impact of these applications on polling HID devices. + If you are using a browser-based tool, leave open only the tab with HID report rate measurement tool to ensure that no other tab influences the measurement. + +Building information +~~~~~~~~~~~~~~~~~~~~ + +Use the :file:`prj_release.conf` configuration for the HID report rate measurement. +Debug features, such as logging or assertions, decrease the application performance. + +Use the nRF Desktop configuration that acts as a HID mouse reference design for the report rate measurement, as the motion data polling is synchronized with sending HID reports. + +Make sure your chosen motion data source will generate movement in each poll interval. +Without a need for user's input, you can generate HID reports that contain mouse movement data. +Use the :ref:`Motion simulated module ` for this. + +To build an application for evaluating HID report rate, run the following command: + + .. parsed-literal:: + :class: highlight + + west build -p -b *build_target* -- \ + -DCONF_FILE=prj_release.conf \ + -DCONFIG_DESKTOP_MOTION_SIMULATED_ENABLE=y \ + +Report rate measuring tips +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See the following list of possible scenarios and best practices: + +* If two or more peripherals are connected through the dongle, and all of the devices support LLPM, the Bluetooth LE LLPM connection events split evenly among all of the peripherals connected through that dongle. + It results in decreased HID report rate. + For example, you should observe a 500 Hz HID report rate when both mouse and keyboard are connected through the dongle and a 1000 Hz rate when only the mouse is connected. +* If a HID peripheral is connected through a dongle, the dongle's performance must be taken into account when measuring the report rate. + Delays related to data forwarding on the dongle also result in reduced report rate. +* If the device is connected through Bluetooth LE directly to the HID host, the host sets the Bluetooth LE connection interval. + A Bluetooth LE peripheral can suggest the preferred connection parameters. + You can set the suggested connection interval using the :kconfig:option:`CONFIG_BT_PERIPHERAL_PREF_MIN_INT` and :kconfig:option:`CONFIG_BT_PERIPHERAL_PREF_MAX_INT` Kconfig options. + Set parameters are not enforced, meaning that the HID host may still eventually use a value greater than the maximum connection interval requested by a peripheral. +* Radio frequency (RF) noise can negatively affect the HID report rate for wireless connections. + If a HID report fails to be delivered in a given Bluetooth LE LLPM connection event, it is retransmitted in the subsequent connection event, which effectively reduces the report rate. + By avoiding congested RF channels, the :ref:`nrf_desktop_ble_qos` helps to achieve better connection quality and a higher report rate. +* For the USB device connected directly, you can configure your preferred USB HID poll interval using the :kconfig:option:`CONFIG_USB_HID_POLL_INTERVAL_MS` Kconfig option. + By default, the :kconfig:option:`CONFIG_USB_HID_POLL_INTERVAL_MS` Kconfig option is set to ``1`` to request the lowest possible poll interval. + Set parameters are not enforced, meaning that the HID host may still eventually use a value greater than the USB polling interval requested by a peripheral. + +Testing steps +~~~~~~~~~~~~~ + +After building the application, test the nRF Desktop by performing the following steps: + +1. Program the device with the built firmware. +#. Connect the device to the computer using a preferred transport (Bluetooth LE, USB, dongle). +#. Turn on the device. + If you use the motion simulated module to generate the mouse movement, the device should automatically start to draw an octagon shape on the screen. + Otherwise, you need to constantly keep generating motion manually, for example, by moving your mouse. +#. Turn off the device to finalize test preparations. +#. Launch selected HID report rate measurement tool. +#. Turn back on the device. +#. Run measurement. +#. Verify the average HID report rate reported by tool. + +Windows Hardware Lab Kit tests +------------------------------ + +The nRF Desktop devices have passed the tests from official playlist required for compatibility with Windows 10 by Windows Hardware Compatibility Program (:file:`HLK Version 1903 CompatPlaylist x86 x64 ARM64.xml`). +The tests were conducted using `Windows Hardware Lab Kit`_. + +Dependencies +************ + +This application uses the following |NCS| libraries and drivers: + +* :ref:`lib_caf` +* :ref:`app_event_manager` +* :ref:`nrf_profiler` +* :ref:`hids_readme` +* :ref:`hogp_readme` +* :ref:`nrf_bt_scan_readme` +* :ref:`gatt_dm_readme` +* :file:`drivers/sensor/paw3212` +* :file:`drivers/sensor/pmw3360` diff --git a/applications/nrf_desktop/doc/battery_charger.rst b/applications/nrf_desktop/doc/battery_charger.rst index 5d561cf77d2..f2a8933cad0 100644 --- a/applications/nrf_desktop/doc/battery_charger.rst +++ b/applications/nrf_desktop/doc/battery_charger.rst @@ -28,7 +28,7 @@ For this reason, you should set :kconfig:option:`CONFIG_GPIO` option. By default, the module is disabled and the :ref:`CONFIG_DESKTOP_BATTERY_CHARGER_NONE ` option is selected. Set the option :ref:`CONFIG_DESKTOP_BATTERY_CHARGER_DISCRETE ` to enable the module. -The module requires a node labeled ``battery_charger`` with a ``battery-charger`` compatible set in Devicetree. +The module requires a node labeled ``battery_charger`` with a ``battery-charger`` compatible set in devicetree. The charge status output (CSO) GPIO spec, the Enable GPIO spec, and the CSO switching frequency properties are also required. See the following snippet for an example: diff --git a/applications/nrf_desktop/doc/ble_qos.rst b/applications/nrf_desktop/doc/ble_qos.rst index 978994531e7..bb63522809b 100644 --- a/applications/nrf_desktop/doc/ble_qos.rst +++ b/applications/nrf_desktop/doc/ble_qos.rst @@ -33,7 +33,7 @@ Enable the module using the :ref:`CONFIG_DESKTOP_BLE_QOS_ENABLE ` option to enable real-time QoS information printouts through a UART (e.g. a virtual COM port). -The chosen UART needs to be specified in Devicetree using ``ncs,ble-qos-uart``. +The chosen UART needs to be specified in devicetree using ``ncs,ble-qos-uart``. This option also enables and configures the COM port (USB CDC ACM). For this reason, the :kconfig:option:`CONFIG_USB_DEVICE_STACK` must be enabled. diff --git a/applications/nrf_desktop/doc/event_propagation.rst b/applications/nrf_desktop/doc/event_propagation.rst index ed5cd201547..9650a70c585 100644 --- a/applications/nrf_desktop/doc/event_propagation.rst +++ b/applications/nrf_desktop/doc/event_propagation.rst @@ -80,39 +80,41 @@ nRF Desktop event propagation .. table_ble_adv_start -+-----------------------------------------------+------------------------------+-------------+---------------------------+---------------------------------------------+ -| Source Module | Input Event | This Module | Output Event | Sink Module | -+===============================================+==============================+=============+===========================+=============================================+ -| :ref:`nrf_desktop_ble_adv` | ``ble_peer_event`` | ``ble_adv`` | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_ble_state` | | | | | -+-----------------------------------------------+------------------------------+ | | | -| :ref:`nrf_desktop_ble_bond` | ``ble_peer_operation_event`` | | | | -+-----------------------------------------------+------------------------------+ | | | -| :ref:`nrf_desktop_module_state_event_sources` | ``module_state_event`` | | | | -+-----------------------------------------------+------------------------------+ | | | -| :ref:`nrf_desktop_power_manager` | ``power_down_event`` | | | | -+-----------------------------------------------+------------------------------+ | | | -| :ref:`nrf_desktop_ble_adv` | ``wake_up_event`` | | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_buttons` | | | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_hid_forward` | | | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_motion` | | | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_power_manager` | | | | | -+-----------------------------------------------+ | | | | -| :ref:`nrf_desktop_wheel` | | | | | -+-----------------------------------------------+------------------------------+ +---------------------------+---------------------------------------------+ -| | | | ``ble_peer_event`` | :ref:`nrf_desktop_ble_peer_event_sinks` | -| | | +---------------------------+---------------------------------------------+ -| | | | ``ble_peer_search_event`` | :ref:`nrf_desktop_led_state` | -| | | +---------------------------+---------------------------------------------+ -| | | | ``module_state_event`` | :ref:`nrf_desktop_module_state_event_sinks` | -| | | +---------------------------+---------------------------------------------+ -| | | | ``wake_up_event`` | :ref:`nrf_desktop_wake_up_event_sinks` | -+-----------------------------------------------+------------------------------+-------------+---------------------------+---------------------------------------------+ ++-----------------------------------------------+------------------------------+-------------+----------------------------+---------------------------------------------+ +| Source Module | Input Event | This Module | Output Event | Sink Module | ++===============================================+==============================+=============+============================+=============================================+ +| :ref:`nrf_desktop_ble_adv` | ``ble_peer_event`` | ``ble_adv`` | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_ble_state` | | | | | ++-----------------------------------------------+------------------------------+ | | | +| :ref:`nrf_desktop_ble_bond` | ``ble_peer_operation_event`` | | | | ++-----------------------------------------------+------------------------------+ | | | +| :ref:`nrf_desktop_module_state_event_sources` | ``module_state_event`` | | | | ++-----------------------------------------------+------------------------------+ | | | +| :ref:`nrf_desktop_power_manager` | ``power_down_event`` | | | | ++-----------------------------------------------+------------------------------+ | | | +| :ref:`nrf_desktop_ble_adv` | ``wake_up_event`` | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_buttons` | | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_hid_forward` | | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_motion` | | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_power_manager` | | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_wheel` | | | | | ++-----------------------------------------------+------------------------------+ +----------------------------+---------------------------------------------+ +| | | | ``ble_peer_event`` | :ref:`nrf_desktop_ble_peer_event_sinks` | +| | | +----------------------------+---------------------------------------------+ +| | | | ``ble_peer_search_event`` | :ref:`nrf_desktop_led_state` | +| | | +----------------------------+---------------------------------------------+ +| | | | ``force_power_down_event`` | :ref:`nrf_desktop_power_manager` | +| | | +----------------------------+---------------------------------------------+ +| | | | ``module_state_event`` | :ref:`nrf_desktop_module_state_event_sinks` | +| | | +----------------------------+---------------------------------------------+ +| | | | ``wake_up_event`` | :ref:`nrf_desktop_wake_up_event_sinks` | ++-----------------------------------------------+------------------------------+-------------+----------------------------+---------------------------------------------+ .. table_ble_adv_end @@ -1121,7 +1123,9 @@ nRF Desktop event propagation +-----------------------------------------------+ | | | | | :ref:`nrf_desktop_wheel` | | | | | +-----------------------------------------------+----------------------------------+ | | | -| :ref:`nrf_desktop_usb_state_pm` | ``force_power_down_event`` | | | | +| :ref:`nrf_desktop_ble_adv` | ``force_power_down_event`` | | | | ++-----------------------------------------------+ | | | | +| :ref:`nrf_desktop_usb_state_pm` | | | | | +-----------------------------------------------+----------------------------------+ | | | | :ref:`nrf_desktop_ble_state_pm` | ``keep_alive_event`` | | | | +-----------------------------------------------+ | | | | diff --git a/applications/nrf_desktop/doc/fast_pair_app.rst b/applications/nrf_desktop/doc/fast_pair_app.rst index 62589d50847..8a89e6c89db 100644 --- a/applications/nrf_desktop/doc/fast_pair_app.rst +++ b/applications/nrf_desktop/doc/fast_pair_app.rst @@ -46,7 +46,7 @@ The option is enabled by default if :kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LO .. note:: If :kconfig:option:`CONFIG_CAF_BLE_STATE_MAX_LOCAL_ID_BONDS` Kconfig option value is equal to one: - * Displaying UI indication during the Fast Pair not discoverable advertising (:kconfig:option:`CONFIG_BT_ADV_PROV_FAST_PAIR_SHOW_UI_PAIRING`) is disabled by default in the nRF Desktop advertising data configuration defined in :file:`src/util/Kconfg` file. + * Displaying UI indication during the Fast Pair not discoverable advertising (:kconfig:option:`CONFIG_BT_ADV_PROV_FAST_PAIR_SHOW_UI_PAIRING`) is disabled by default in the nRF Desktop advertising data configuration defined in :file:`src/util/Kconfig` file. * :ref:`nrf_desktop_ble_state` automatically disconnects new peers right after Bluetooth connection is established if the used Bluetooth local identity is already bonded with another peer. The :ref:`CONFIG_DESKTOP_FAST_PAIR_LIMIT_NORMAL_PAIRING ` can be used to allow normal Bluetooth pairing only in the pairing mode. @@ -64,5 +64,5 @@ This allows the module to update the Fast Pair advertising payload just before t The module is a subscriber for :c:struct:`ble_dongle_peer_event`. This allows the module to remove the Fast Pair advertising payload when the application identity of the dongle peer is used. -The module registers the global application's Bluetooth authentication callbacks (:c:struct:`bt_conn_auth_cb`) on application start. +The module registers the global application's Bluetooth authentication callbacks (:c:struct:`bt_conn_auth_cb`) and enables the :ref:`bt_fast_pair_readme` (:c:func:`bt_fast_pair_enable`) after :ref:`caf_settings_loader` loads Zephyr's :ref:`zephyr:settings_api`. The callbacks are used to reject normal Bluetooth pairing when outside of the pairing mode. diff --git a/applications/nrf_desktop/doc/hid_state.rst b/applications/nrf_desktop/doc/hid_state.rst index bf6e7fe1248..1bc4efd32a4 100644 --- a/applications/nrf_desktop/doc/hid_state.rst +++ b/applications/nrf_desktop/doc/hid_state.rst @@ -38,6 +38,13 @@ To send boot reports, enable the respective Kconfig option: * :ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD ` - This option enables sending keyboard boot reports. * :ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_MOUSE ` - This option enables sending mouse boot reports. +Number of supported HID data subscribers +======================================== + +If your application configuration supports more than one HID data subscriber, you must align the maximum number of HID data subscribers that can be supported simultaneously (:ref:`CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT `). +For example, to use a configuration that allows to simultaneously subscribe for HID reports from HID over GATT (BLE) and a single USB HID instance, set the value of this Kconfig option to ``2``. +See the `Tracking state of transports`_ section for more details about HID subscribers. + HID keymap ========== @@ -128,7 +135,7 @@ The |hid_state| provides a routing mechanism between sources of input data and t This can be associated with: * Receiving input events from :ref:`caf_buttons`, :ref:`nrf_desktop_wheel`, and :ref:`nrf_desktop_motion`. -* Sending out HID reports to :ref:`nrf_desktop_hids` and :ref:`nrf_desktop_usb_state`. +* Sending out HID reports to HID transports, for example, :ref:`nrf_desktop_hids` and :ref:`nrf_desktop_usb_state`. For the routing mechanism to work, the module performs the following operations: @@ -226,15 +233,14 @@ Once connection is established, the elements of the queue are replayed one after Tracking state of transports ============================ -The |hid_state| refers collectively to all transports as _subscribers_. - -The module tracks the state of the connected Bluetooth® LE peers and the state of USB by listening to :c:struct:`hid_report_subscriber_event`. +The |hid_state| tracks the state of modules that forward the HID data to a HID host (HID transports) by listening to :c:struct:`hid_report_subscriber_event`. +The |hid_state| refers collectively to all transports as *subscribers*. When the connection to the host is indicated by this event, the |hid_state| will create a subscriber associated with the transport. - Each subscriber reports its priority as part of the :c:struct:`hid_report_subscriber_event`. The subscriber priority must be unique, that mean two or more subscriber cannot share the same priority value. + By default, the subscriber that is associated with USB has priority over any Bluetooth LE peer subscriber. -As a result, when the device connects to the host through USB, all HID reports will be routed to USB. +As a result, when the host connected through the USB subscribes for a HID report, the HID report will be routed to the USB. Tracking state of HID report notifications ========================================== diff --git a/applications/nrf_desktop/doc/wheel.rst b/applications/nrf_desktop/doc/wheel.rst index 580c0f4d74b..e239dbe2279 100644 --- a/applications/nrf_desktop/doc/wheel.rst +++ b/applications/nrf_desktop/doc/wheel.rst @@ -25,7 +25,9 @@ Configuration Enable the module with the :ref:`CONFIG_DESKTOP_WHEEL_ENABLE ` Kconfig option. For detecting rotation, the wheel module uses Zephyr's QDEC driver. -The module can be enabled only when QDEC is configured in DTS (that is, :kconfig:option:`CONFIG_QDEC_NRFX` is set). +You can enable the module only when QDEC is configured in DTS and the Zephyr's QDEC driver is enabled with the :kconfig:option:`CONFIG_QDEC_NRFX` Kconfig option. +If your board supports multiple QDEC instances (for example ``nrf54l15pdk_nrf54l15_cpuapp``), you also need to specify the used QDEC instance with the ``nrfdesktop-wheel-qdec`` DT alias. +If your board supports only one QDEC instance, the module relies on the ``qdec`` DT label and you do not need to define the DT alias. The QDEC DTS configuration specifies how many steps are done during one full angle. The sensor reports the rotation data in angle degrees. diff --git a/applications/nrf_desktop/fwupd.rst b/applications/nrf_desktop/fwupd.rst new file mode 100644 index 00000000000..b184b155042 --- /dev/null +++ b/applications/nrf_desktop/fwupd.rst @@ -0,0 +1,101 @@ +.. _nrf_desktop_fwupd: + +nRF Desktop: fwupd support +########################## + +.. contents:: + :local: + :depth: 2 + +fwupd is an open-source project providing tools and daemon for managing the installation of firmware updates on Linux-based systems. +Together with the `LVFS (Linux Vendor Firmware Service) `_, it provides a solution for vendors to easily distribute firmware for compatible devices. + +The fwupd tools can communicate with devices running the nRF Desktop application with the :ref:`nrf_desktop_bootloader_background_dfu` feature enabled. + +Nordic HID plugin +***************** + +The fwupd project allows communication with multiple types of devices through various communication protocols. +The communication protocols are implemented using plugins. +The plugin associated with the DFU protocol realized through the :ref:`nrf_desktop_config_channel` is branded as ``nordic_hid``. + +Adding a new device +******************* + +The device specifies which protocol is used for the communication by adding the specific device information to the plugin metadata. +For the ``nordic_hid`` plugin, this file is located at `nordic-hid.quirk`_. +The following example shows the information passed to the plugin metadata: + +.. code-block:: console + + [HIDRAW\VEN_1915&DEV_52DE] + Plugin = nordic_hid + GType = FuNordicHidCfgChannel + NordicHidBootloader = B0 + +In this console snippet: + +* ``[HIDRAW\VEN_1915&DEV_52DE]`` - This line describes the device instance ID provided by the OS, which identifies the device. +* ``Plugin = nordic_hid`` and ``GType = FuNordicHidCfgChannel`` - These lines set the plugin that the device uses. +* ``NordicHidBootloader`` - This optional line selects the bootloader that the device is running. + If the device does not have the information about the underlying bootloader, the ``NordicHidBootloader`` option is used to select a proper bootloader type. + If there is no information about the bootloader, both in metadata and from the device, the update procedure fails. + The possible values are either ``B0``, ``MCUBOOT``, or ``MCUBOOT+XIP``. + +.. note:: + As the ``nordic_hid`` plugin communicates with the device using the Configuration channel, the device update is not allowed through the Serial recovery DFU. + +To add a new device, a pull request must be opened to the `fwupd`_ repository with a new entry to the :file:`nordic-hid.quirk` file. + +LVFS and update image preparation +********************************* + +The `LVFS (Linux Vendor Firmware Service) `_ hosts firmware images that can be downloaded by Linux machines and used by the fwupd tool for the firmware update of compatible devices. +A vendor account is needed to upload a new firmware archive to the site. +Information on how to apply for an account is found at the `LVFS Getting an account`_ website. + +The nRF Desktop application DFU image is delivered as a zip package, containing a manifest and one or more binary files used for the update. +To prepare an image file compatible with the LVFS, you must prepare a CAB file. +The CAB archive must contain the DFU package generated by the |NCS|, that is :file:`dfu_application.zip`, plus metadata file with information used by the LVFS. +For more information, see the `LVFS metadata`_ site. + +When the CAB archive has been built, it can be uploaded to the LVFS where it is verified and signed. +For more information about creating CAB files, signing, and uploading the update package, see the `LVFS Uploading Firmware`_ site. + +Upgrading firmware using fwupd +****************************** + +Once the update image is uploaded onto the LVFS, you can test the firmware update procedure on HID hosts that support fwupd. + +Complete the following steps: + +1. Make sure that the host machine to which the updatable device running the nRF Desktop application is connected has the fwupd tool installed. +#. Fetch the information about available update images from the LVFS using the following commands: + + .. code-block:: console + + fwupdmgr refresh + fwupdmgr get-updates + + * ``fwupdmgr refresh`` - This command downloads the latest metadata from the LVFS. + * ``fwupdmgr get-updates`` - This command displays the updates available for the devices on the host system. + +#. Test the update image on a limited number of devices before it goes public. + For more information about limiting the visibility of updated images uploaded to the LVFS, see the `LVFS testing`_ site. +#. Run the following command to update the devices: + + .. code-block:: console + + fwupdmgr update + +When connecting to the device, the application verifies the bootloader type. +This is done to ensure a compatible firmware is uploaded to the nRF Desktop device, that is software that can support multiple bootloaders. +The device is queried for information about bootloader using the :ref:`nrf_desktop_config_channel`. +If the device does not provide information about the bootloader type, such information can optionally be provided inside the :file:`nordic-hid.quirk` file (see the ``NordicHidBootloader`` option under `Adding a new device`_). + +fwupd can fail the image update in the following cases: + +* When the bootloader information stored in an updated image does not match the type reported by the device. +* When there is no information about the bootloader used on the device. + +For more information about building the fwupd tool locally, see the `LVFS building fwupd`_ site. diff --git a/applications/nrf_desktop/integration.rst b/applications/nrf_desktop/integration.rst new file mode 100644 index 00000000000..51bf5f9ad0b --- /dev/null +++ b/applications/nrf_desktop/integration.rst @@ -0,0 +1,273 @@ +.. _nrf_desktop_porting_guide: + +nRF Desktop: Integrating your own hardware +########################################## + +.. contents:: + :local: + :depth: 2 + +This page describes how to adapt the nRF Desktop application to different hardware and lists the required steps. + +.. tip:: + Make sure to get familiar with the :ref:`nrf_desktop_configuration` section before porting the application to a new board. + +.. _porting_guide_adding_board: + +Adding a new board +****************** + +When adding a new board for the first time, focus on a single configuration. +Moreover, keep the default ``debug`` build type that the application is built with, and do not add any additional build type parameters. +The following procedure uses the gaming mouse configuration as an example. + +Zephyr support for a board +========================== + +Before introducing nRF Desktop application configuration for a given board, you need to ensure that the board is supported in Zephyr. + +.. note:: + You can skip this step if your selected board is already supported in Zephyr. + +Follow the Zephyr's :ref:`zephyr:board_porting_guide` for detailed instructions related to introducing Zephyr support for a new board. +Make sure that the following conditions are met: + +* Edit the DTS files to make sure they match the hardware configuration. + Pay attention to the following elements: + + * Pins that are used. + * Bus configuration for optical sensor. + * `Changing interrupt priority`_. + +* Edit the board's Kconfig files to make sure they match the required system configuration. + For example, disable the drivers that will not be used by your device. + +.. tip:: + You can define the new board by copying the nRF Desktop reference design files that are the closest match for your hardware and then aligning the configuration to your hardware. + For example, for gaming mouse use :file:`nrf/boards/arm/nrf52840gmouse_nrf52840`. + +nRF Desktop support for a board +=============================== + +Perform the following steps to add nRF Desktop application configuration for a board that is already supported in Zephyr. + +1. Copy the project files for the device that is the closest match for your hardware. + For example, for gaming mouse these are located at :file:`applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840`. +#. Optionally, depending on the reference design, edit the DTS overlay file. + This step is not required if you have created a new reference design and its DTS files fully describe your hardware. + In such case, the overlay file can be left empty. +#. In Kconfig, ensure that the following hardware interface modules that are specific for gaming mouse are enabled: + + * :ref:`caf_buttons` + * :ref:`caf_leds` + * :ref:`nrf_desktop_motion` + * :ref:`nrf_desktop_wheel` + * :ref:`nrf_desktop_battery_meas` + +#. For each module enabled, change its configuration to match your hardware. + Apply the following changes, depending on the module: + + Motion module + * The ``nrf52840gmouse_nrf52840`` uses the PMW3360 optical motion sensor. + The sensor is configured in DTS, and the sensor type is selected in the application configuration. + To add a new sensor, expand the application configuration. + Wheel module + * The wheel is based on the QDEC peripheral of the nRF52840 device and the hardware-related part is configured in DTS. + Buttons module + * To simplify the configuration of arrays, the nRF Desktop application uses :file:`_def` files. + * The :file:`_def` file of the buttons module contains pins assigned to rows and columns. + Battery measurement module + * The :file:`_def` file of the battery measurement module contains the mapping needed to match the voltage that is read from ADC to the battery level. + LEDs module + * The application uses two logical LEDs - one for the peers state, and one for the system state indication. + * Each of the logical LEDs can have either one (monochromatic) or three color channels (RGB). + Such color channel is a physical LED. + * The module uses Zephyr's :ref:`zephyr:led_api` driver for setting the LED color. + Zephyr's LED driver can use the implementation based on either GPIO or PWM (Pulse-Width Modulation). + The hardware configuration is described through DTS. + See the :ref:`caf_leds` configuration section for details. + +#. Review the :ref:`nrf_desktop_hid_configuration`. +#. By default, the nRF Desktop device enables Bluetooth connectivity support. + Review the :ref:`nrf_desktop_bluetooth_configuration`. + + a. Ensure that the Bluetooth role is properly configured. + For mouse, it should be configured as peripheral. + #. Update the configuration related to peer control. + You can also disable the peer control using the :ref:`CONFIG_DESKTOP_BLE_PEER_CONTROL ` option. + Peer control details are described in the :ref:`nrf_desktop_ble_bond` documentation. + +#. Edit Kconfig to disable options that you do not use. + Some options have dependencies that might not be needed when these options are disabled. + For example, when the LEDs module is disabled, the PWM driver is not needed. + +.. _porting_guide_adding_sensor: + +Adding a new motion sensor +************************** + +This procedure describes how to add a new motion sensor into the project. +You can use it as a reference for adding other hardware components. + +The nRF Desktop application comes with a :ref:`nrf_desktop_motion` that is able to read data from a motion sensor. +While |NCS| provides support for two motion sensor drivers (PMW3360 and PAW3212), you can add support for a different sensor, based on your development needs. + +Complete the steps described in the following sections to add a new motion sensor. + +.. rst-class:: numbered-step + +Add a new sensor driver +======================= + +First, create a new motion sensor driver that will provide code for communication with the sensor. +Use the two existing |NCS| sensor drivers as an example. + +The communication between the application and the sensor happens through a sensor driver API (see :ref:`sensor_api`). +For the motion module to work correctly, the driver must support a trigger (see ``sensor_trigger_set``) on a new data (see ``SENSOR_TRIG_DATA_READY`` trigger type). + +When the motion data is ready, the driver calls a registered callback. +The application starts a process of retrieving a motion data sample. +The motion module calls ``sensor_sample_fetch`` and then ``sensor_channel_get`` on two sensor channels, ``SENSOR_CHAN_POS_DX`` and ``SENSOR_CHAN_POS_DY``. +The driver must support these two channels. + +.. rst-class:: numbered-step + +Create a DTS binding +==================== + +Zephyr recommends to use DTS for hardware configuration (see :ref:`zephyr:dt_vs_kconfig`). +For the new motion sensor configuration to be recognized by DTS, define a dedicated DTS binding. +See :ref:`dt-bindings` for more information, and refer to :file:`dts/bindings/sensor` for binding examples. + +.. rst-class:: numbered-step + +Configure sensor through DTS +============================ + +Once binding is defined, it is possible to set the sensor configuration. +To define the binding, edit the DTS file that describes the board. +For more information, see :ref:`devicetree-intro`. + +As an example, take a look at the PMW3360 sensor that is already available in the |NCS|. +The following code excerpt is taken from :file:`boards/arm/nrf52840gmouse_nrf52840/nrf52840gmouse_nrf52840.dts`: + +.. code-block:: none + + &spi1 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 13 0>; + + pinctrl-0 = <&spi1_default_alt>; + pinctrl-1 = <&spi1_sleep_alt>; + pinctrl-names = "default", "sleep"; + pmw3360@0 { + compatible = "pixart,pmw3360"; + reg = <0>; + irq-gpios = <&gpio0 21 0>; + spi-max-frequency = <2000000>; + }; + }; + +The communication with PMW3360 happens through the SPI, which makes the sensor a subnode of the SPI bus node. +SPI pins are defined as part of the bus configuration, as these are common among all devices connected to this bus. +In this case, the PMW3360 sensor is the only device on this bus, so there is only one pin specified for selecting the chip. + +When the sensor's node is mentioned, you can read ``@0`` in ``pmw3360@0``. +For SPI devices, ``@0`` refers to the position of the chip select pin in the ``cs-gpios`` array for a corresponding device. + +Note the string ``compatible = "pixart,pmw3360"`` in the subnode configuration. +This string indicates which DTS binding the node will use. +The binding should match with the DTS binding created earlier for the sensor. + +The following options are inherited from the ``spi-device`` binding and are common to all SPI devices: + +* ``reg`` - The slave ID number the device has on a bus. +* ``label`` - Used to generate a name of the device (for example, it will be added to generated macros). +* ``spi-max-frequency`` - Used for setting the bus clock frequency. + + .. note:: + To achieve full speed, data must be propagated through the application and reach Bluetooth LE a few hundred microseconds before the subsequent connection event. + If you aim for the lowest latency through the LLPM (an interval of 1 ms), the sensor data readout should take no more than 250 µs. + The bus and the sensor configuration must ensure that communication speed is high enough. + +The remaining option ``irq-gpios`` is specific to ``pixart,pmw3360`` binding. +It refers to the PIN to which the motion sensor IRQ line is connected. + +If a different kind of bus is used for the new sensor, the DTS layout will be different. + +.. rst-class:: numbered-step + +Include sensor in the application +================================= + +Once the new sensor is supported by the |NCS| and the board configuration is updated, you can include it in the nRF Desktop application. + +The nRF Desktop application selects a sensor using the configuration options defined in :file:`src/hw_interface/Kconfig.motion`. +Add the new sensor as a new choice option. + +The :ref:`nrf_desktop_motion` of the nRF Desktop application has access to several sensor attributes. +These attributes are used to modify the sensor behavior in runtime. +Since the names of the attributes differ for each sensor, the :ref:`nrf_desktop_motion` uses a generic abstraction of them. +You can translate the new sensor-specific attributes to a generic abstraction by modifying the :file:`configuration/common/motion_sensor.h` file. + +.. tip:: + If an attribute is not supported by the sensor, you do not need to define it. + In such case, set the attribute to ``-ENOTSUP``. + +.. rst-class:: numbered-step + +Select the new sensor +===================== + +The application can now use the new sensor. +Edit the application configuration files for your board to enable it. +See :ref:`nrf_desktop_board_configuration` for details. + +To start using the new sensor, complete the following steps: + +1. Enable all dependencies required by the driver (for example, bus driver). +#. Enable the new sensor driver. +#. Select the new sensor driver in the application configuration options. + +Changing interrupt priority +=========================== + +You can edit the DTS files to change the priority of the peripheral's interrupt. +This can be useful when :ref:`adding a new custom board ` or whenever you need to change the interrupt priority. + +The ``interrupts`` property is an array, where the meaning of each element is defined by the specification of the interrupt controller. +These specification files are located at :file:`zephyr/dts/bindings/interrupt-controller/` DTS binding file directory. + +For example, for nRF52840, the file is :file:`arm,v7m-nvic.yaml`. +This file defines the ``interrupts`` property in the ``interrupt-cells`` list. +For nRF52840, it contains two elements: ``irq`` and ``priority``. +The default values for these elements for the given peripheral are in the :file:`dtsi` file specific for the device. +In the case of nRF52840, this is :file:`zephyr/dts/arm/nordic/nrf52840.dtsi`, which has the following ``interrupts``: + +.. code-block:: + + spi1: spi@40004000 { + /* + * This spi node can be SPI, SPIM, or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spi" or + * "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40004000 0x1000>; + interrupts = <4 1>; + status = "disabled"; + }; + +To change the priority of the peripheral's interrupt, override the ``interrupts`` property of the peripheral node by including the following code snippet in the :file:`dts.overlay` file or directly in the board DTS: + +.. code-block:: none + + &spi1 { + interrupts = <4 2>; + }; + +This code snippet changes the **SPI1** interrupt priority from default ``1`` to ``2``. diff --git a/applications/nrf_desktop/memory_layout.rst b/applications/nrf_desktop/memory_layout.rst new file mode 100644 index 00000000000..0796ca5316b --- /dev/null +++ b/applications/nrf_desktop/memory_layout.rst @@ -0,0 +1,90 @@ +.. _nrf_desktop_memory_layout: + +nRF Desktop: Memory layout +########################## + +.. contents:: + :local: + :depth: 2 + +You must define the memory layout as a part of the application configuration for a given board. +The set of required partitions differs depending on the configuration: + +* There must be at least one partition where the code is stored. +* There must be one partition for storing :ref:`zephyr:settings_api`. +* If the bootloader is enabled, it adds more partitions to the set. +* When using an SoC with multiple cores, the firmware for additional cores adds more partitions to the set. + For example, the network core of the nRF53 SoC uses the ``HCI IPC`` firmware image, which allows to use the core for Bluetooth LE communication. + +.. important:: + Before updating the firmware, make sure that the data stored in the settings partition is compatible with the new firmware. + If it is incompatible, erase the settings area before using the new firmware. + +The memory layout is defined through one of the following methods: + +* `Memory layout in DTS`_ +* `Memory layout in Partition Manager`_ + +By default, a Zephyr-based application defines the memory layout in the DTS. +If enabled, the :ref:`partition_manager` defines a new memory layout that is used instead of the memory layout defined in the DTS. +You can use the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` Kconfig option value to check whether the Partition Manager is enabled in the current build. +The option is automatically selected as part of the :ref:`ug_multi_image` feature to build the application with more than one image. +Enabling the :ref:`nrf_desktop_bluetooth_guide_fast_pair` also results in using the Partition Manager. +To store the Fast Pair Provisioning data, the Fast Pair integration in the |NCS| uses partition defined by the Partition Manager. + +Memory layout in DTS +******************** + +If you rely on a non-volatile memory layout described in DTS files, define the ``partitions`` child node under the DTS node that represents the non-volatile memory. +For example, the nRF52 Series devices use non-volatile flash memory represented by the flash device node (``&flash0``). +Make sure to also update the DTS chosen nodes, which represent the code partition (``zephyr,code-partition``) and flash (``zephyr,flash``), if needed. + +If you wish to change the default memory layout of the board without editing the board-specific files, edit the DTS overlay file. +The nRF Desktop application automatically adds the :file:`dts.overlay` file if it is present in the project's board configuration directory. +For more details, see the :ref:`nrf_desktop_board_configuration` section. + +.. important:: + By default, Zephyr does not use the code partition defined in the DTS files. + It is only used if the :kconfig:option:`CONFIG_USE_DT_CODE_PARTITION` Kconfig option is enabled. + If this option is disabled, the code is loaded at the offset defined by the :kconfig:option:`CONFIG_FLASH_LOAD_OFFSET` Kconfig option. + In that case, the code spawns for :kconfig:option:`CONFIG_FLASH_LOAD_SIZE` (or for the whole remaining chosen ``zephyr,flash`` memory if the load size is set to ``0``). + The settings memory partition definition is still used by the firmware even if the :kconfig:option:`CONFIG_USE_DT_CODE_PARTITION` Kconfig option is disabled. + +For more information about how to configure the non-volatile memory layout in the DTS files, see :ref:`zephyr:flash_map_api`. + +Memory layout in Partition Manager +********************************** + +When the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` Kconfig option is enabled, the nRF Desktop application uses the Partition Manager for the memory layout configuration. +The nRF Desktop configurations use static configurations of partitions to ensure that the partition layout does not change between builds. + +Add the :file:`pm_static_${BUILD_TYPE}.yml` file to the project's board configuration directory to define the static Partition Manager configuration for given board and build type. +For example, to define the static partition layout for the ``nrf52840dk_nrf52840`` board and ``release`` build type, you would need to add the :file:`pm_static_release.yml` file into the :file:`applicatons/nrf_desktop/configuration/nrf52840dk_nrf52840` directory. + +Take into account the following points: + +* For the :ref:`background firmware upgrade `, you must define the secondary image partition. + This is because the update image is stored on the secondary image partition while the device is running firmware from the primary partition. + For this reason, the feature is not available for devices with smaller non-volatile memory size, because the size of the required non-volatile memory is essentially doubled. + The devices with smaller non-volatile memory size can use either USB serial recovery or the MCUboot bootloader with the secondary image partition located on an external non-volatile memory. +* When you use :ref:`USB serial recovery `, you do not need the secondary image partition. + The firmware image is overwritten by the bootloader. + +For an example of configuration, see the static partition maps defined for the existing configuration that uses a given DFU method. +For more information about how to configure the non-volatile memory layout using the Partition Manager, see :ref:`partition_manager`. + +.. _nrf_desktop_pm_external_flash: + +External flash configuration +============================ + +The Partition Manager supports partitions in external flash. + +Enabling external flash can be useful especially for memory-limited devices. +For example, the MCUboot can use it as a secondary image partition for the :ref:`background firmware upgrade `. +The MCUboot moves the image data from the secondary image partition to the primary image partition before booting the new firmware. + +For an example of the nRF Desktop application configuration that uses an external flash, see the ``mcuboot_qspi`` configuration of the nRF52840 Development Kit (DK). +This configuration uses the ``MX25R64`` external flash that is part of the development kit. + +For detailed information, see the :ref:`partition_manager` documentation. diff --git a/applications/nrf_desktop/modules.rst b/applications/nrf_desktop/modules.rst new file mode 100644 index 00000000000..69ff8302f84 --- /dev/null +++ b/applications/nrf_desktop/modules.rst @@ -0,0 +1,74 @@ +.. _nrf_desktop_app_internal_modules: + +nRF Desktop: Application internal modules +######################################### + +.. contents:: + :local: + :depth: 2 + + +The nRF Desktop application uses its own set of internal modules. +See :ref:`nrf_desktop_module_component` for more information. +More information about each application module and its configuration details is available on the subpages. + +Each module documentation page has a table that shows the relations between module events. +:ref:`nrf_desktop_module_table` for some modules include extensive lists of source and sink modules. +These are valid for events that have many listeners or sources, and are gathered on the :ref:`nrf_desktop_event_rel_modules` subpage. + +.. toctree:: + :maxdepth: 1 + :caption: Subpages: + + doc/main.rst + doc/battery_charger.rst + doc/battery_meas.rst + doc/ble_adv.rst + doc/ble_bond.rst + doc/ble_conn_params.rst + doc/ble_discovery.rst + doc/ble_latency.rst + doc/ble_passkey.rst + doc/ble_qos.rst + doc/ble_scan.rst + doc/ble_state_pm.rst + doc/ble_state.rst + doc/board.rst + doc/buttons.rst + doc/buttons_sim.rst + doc/click_detector.rst + doc/config_channel.rst + doc/cpu_meas.rst + doc/dev_descr.rst + doc/dfu.rst + doc/dfu_mcumgr.rst + doc/dfu_lock.rst + doc/factory_reset.rst + doc/failsafe.rst + doc/fast_pair_app.rst + doc/fn_keys.rst + doc/bas.rst + doc/hid_forward.rst + doc/hid_state.rst + doc/hid_state_pm.rst + doc/hids.rst + doc/info.rst + doc/led_state.rst + doc/led_stream.rst + doc/leds.rst + doc/motion.rst + doc/passkey.rst + doc/power_manager.rst + doc/nrf_profiler_sync.rst + doc/qos.rst + doc/selector.rst + doc/smp.rst + doc/settings_loader.rst + doc/swift_pair_app.rst + doc/usb_state_pm.rst + doc/usb_state.rst + doc/watchdog.rst + doc/wheel.rst + doc/constlat.rst + doc/hfclk_lock.rst + doc/event_rel_modules.rst diff --git a/applications/nrf_desktop/nRF21540ek_support.rst b/applications/nrf_desktop/nRF21540ek_support.rst new file mode 100644 index 00000000000..122d2dfaf43 --- /dev/null +++ b/applications/nrf_desktop/nRF21540ek_support.rst @@ -0,0 +1,40 @@ +.. _nrf_desktop_nrf21540ek: + +nRF Desktop: Adding nRF21540 EK shield support +############################################## + +.. contents:: + :local: + :depth: 2 + +You can use the nRF Desktop application with the :ref:`ug_radio_fem_nrf21540ek` shield, an RF front-end module (FEM) for the 2.4 GHz range extension. +You can use the shield with any nRF Desktop HID application configured for a development kit that is fitted with Arduino-compatible connector (see the :guilabel:`DK` tab in :ref:`nrf_desktop_requirements`). +This means that the shield support is not available for nRF Desktop's dedicated boards, such as ``nrf52840gmouse_nrf52840``, ``nrf52kbd_nrf52832``, or ``nrf52840dongle_nrf52840``. + +Low Latency Packet mode +*********************** + +You cannot use the RF front-end module (FEM) together with Low Latency Packet Mode (LLPM) due to timing requirements. +You must disable the LLPM support in the nRF Desktop application (:kconfig:option:`CONFIG_CAF_BLE_USE_LLPM`) for builds with FEM. + +Building with EK shield support +******************************* + +To build the application with the shield support, pass the ``SHIELD`` parameter to the build command. +Make sure to also disable the LLPM support. +For example, you can build the application for ``nrf52840dk_nrf52840`` with ``nrf21540ek`` shield using the following command: + +.. code-block:: console + + west build -b nrf52840dk_nrf52840 -- -DSHIELD=nrf21540ek -DCONFIG_CAF_BLE_USE_LLPM=n + +For the multi-core build, you need to pass the ``SHIELD`` parameter to images built on both application and network core. +The network core controls the FEM, but the application core needs to forward the needed pins to the network core. +Use ``hci_ipc_`` as the *childImageName* parameter, because in the nRF Desktop application, network core runs using ``hci_ipc_``. +The command for ``nrf5340dk_nrf5340_cpuapp`` with ``nrf21540ek`` shield would look as follows: + +.. code-block:: console + + west build -b nrf5340dk_nrf5340_cpuapp -- -DSHIELD=nrf21540ek_fwd -Dhci_ipc_SHIELD=nrf21540ek -DCONFIG_CAF_BLE_USE_LLPM=n + +For detailed information about building an application using the nRF21540 EK, see the :ref:`ug_radio_fem_nrf21540ek_programming` section in the Working with RF Front-end modules documentation. diff --git a/applications/nrf_desktop/sample.yaml b/applications/nrf_desktop/sample.yaml index 8e95a7c782c..494cb07a572 100644 --- a/applications/nrf_desktop/sample.yaml +++ b/applications/nrf_desktop/sample.yaml @@ -8,6 +8,7 @@ tests: nrf52dmouse_nrf52832 nrf52kbd_nrf52832 nrf52810dmouse_nrf52810 nrf52820dongle_nrf52820 nrf52833dk_nrf52820 nrf52833dk_nrf52833 nrf52833dongle_nrf52833 nrf52840dk_nrf52840 nrf52840dongle_nrf52840 nrf52840gmouse_nrf52840 nrf5340dk_nrf5340_cpuapp + nrf54l15pdk_nrf54l15_cpuapp integration_platforms: - nrf52dmouse_nrf52832 - nrf52kbd_nrf52832 @@ -20,6 +21,7 @@ tests: - nrf52840dongle_nrf52840 - nrf52840gmouse_nrf52840 - nrf5340dk_nrf5340_cpuapp + - nrf54l15pdk_nrf54l15_cpuapp tags: bluetooth ci_build applications.nrf_desktop.zdebug_wwcb: build_only: true @@ -91,9 +93,10 @@ tests: extra_args: CONF_FILE=prj_dongle.conf applications.nrf_desktop.zdebug_keyboard: build_only: true - platform_allow: nrf52840dk_nrf52840 + platform_allow: nrf52840dk_nrf52840 nrf54l15pdk_nrf54l15_cpuapp integration_platforms: - nrf52840dk_nrf52840 + - nrf54l15pdk_nrf54l15_cpuapp tags: bluetooth ci_build extra_args: CONF_FILE=prj_keyboard.conf applications.nrf_desktop.zdebug_nrf21540ek: @@ -121,6 +124,7 @@ tests: nrf52dmouse_nrf52832 nrf52kbd_nrf52832 nrf52810dmouse_nrf52810 nrf52820dongle_nrf52820 nrf52833dk_nrf52820 nrf52833dk_nrf52833 nrf52833dongle_nrf52833 nrf52840dk_nrf52840 nrf52840dongle_nrf52840 nrf52840gmouse_nrf52840 nrf5340dk_nrf5340_cpuapp + nrf54l15pdk_nrf54l15_cpuapp integration_platforms: - nrf52dmouse_nrf52832 - nrf52kbd_nrf52832 @@ -133,6 +137,7 @@ tests: - nrf52840dongle_nrf52840 - nrf52840gmouse_nrf52840 - nrf5340dk_nrf5340_cpuapp + - nrf54l15pdk_nrf54l15_cpuapp tags: bluetooth ci_build extra_args: CONF_FILE=prj_release.conf applications.nrf_desktop.zrelease_fast_pair.keyboard: diff --git a/applications/nrf_desktop/src/hw_interface/Kconfig.wheel b/applications/nrf_desktop/src/hw_interface/Kconfig.wheel index 78f50371f3a..37b14874d78 100644 --- a/applications/nrf_desktop/src/hw_interface/Kconfig.wheel +++ b/applications/nrf_desktop/src/hw_interface/Kconfig.wheel @@ -10,6 +10,7 @@ menu "Wheel configuration" config DESKTOP_WHEEL_ENABLE bool "Enable wheel hardware interface" depends on QDEC_NRFX + depends on PINCTRL help This option enables wheel hardware interface for nRF Desktop application. Wheel hardware interface is responsible for generating events related to rotation of the diff --git a/applications/nrf_desktop/src/hw_interface/wheel.c b/applications/nrf_desktop/src/hw_interface/wheel.c index 1259a5f904a..bb12cecac51 100644 --- a/applications/nrf_desktop/src/hw_interface/wheel.c +++ b/applications/nrf_desktop/src/hw_interface/wheel.c @@ -13,9 +13,7 @@ #include #include #include -#ifdef CONFIG_PINCTRL #include -#endif #include #include "wheel_event.h" @@ -27,7 +25,7 @@ #include LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_WHEEL_LOG_LEVEL); - +#define PINS_PER_GPIO_PORT 32 #define SENSOR_IDLE_TIMEOUT \ (CONFIG_DESKTOP_WHEEL_SENSOR_IDLE_TIMEOUT * MSEC_PER_SEC) /* ms */ @@ -39,32 +37,32 @@ enum state { STATE_SUSPENDED }; -#ifdef CONFIG_PINCTRL +#if DT_NODE_HAS_STATUS(DT_ALIAS(nrfdesktop_wheel_qdec), okay) + #define QDEC_DT_NODE_ID DT_ALIAS(nrfdesktop_wheel_qdec) +#elif DT_NODE_HAS_STATUS(DT_NODELABEL(qdec), okay) + #define QDEC_DT_NODE_ID DT_NODELABEL(qdec) +#else + #error DT node for QDEC must be specified. +#endif + #define QDEC_PIN_INIT(node_id, prop, idx) \ NRF_GET_PIN(DT_PROP_BY_IDX(node_id, prop, idx)), /* obtan qdec pins from default state */ static const uint32_t qdec_pin[] = { DT_FOREACH_CHILD_VARGS( - DT_PINCTRL_BY_NAME(DT_NODELABEL(qdec), default, 0), + DT_PINCTRL_BY_NAME(QDEC_DT_NODE_ID, default, 0), DT_FOREACH_PROP_ELEM, psels, QDEC_PIN_INIT ) }; -#else -static const uint32_t qdec_pin[] = { - DT_PROP(DT_NODELABEL(qdec), a_pin), - DT_PROP(DT_NODELABEL(qdec), b_pin) -}; -#endif static const struct sensor_trigger qdec_trig = { .type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION, }; -static const struct device *qdec_dev = DEVICE_DT_GET(DT_NODELABEL(qdec)); -static const struct device *const gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)); -static struct gpio_callback gpio_cbs[2]; +static const struct device *qdec_dev = DEVICE_DT_GET(QDEC_DT_NODE_ID); +static struct gpio_callback gpio_cbs[ARRAY_SIZE(qdec_pin)]; static struct k_spinlock lock; static struct k_work_delayable idle_timeout; static bool qdec_triggered; @@ -73,6 +71,39 @@ static enum state state; static int enable_qdec(enum state next_state); +static const struct device *map_gpio_port(int pin_number) +{ + __ASSERT_NO_MSG(pin_number >= 0); + + size_t port_idx = pin_number / PINS_PER_GPIO_PORT; + const struct device *dev = NULL; + + switch (port_idx) { + case 0: + dev = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio0)); + break; + + case 1: + dev = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpio1)); + break; + + default: + break; + } + + /* Assert proper configuration. */ + __ASSERT_NO_MSG(dev); + + return dev; +} + +static gpio_pin_t map_gpio_pin(int pin_number) +{ + __ASSERT_NO_MSG(pin_number >= 0); + + return pin_number % PINS_PER_GPIO_PORT; +} + static void data_ready_handler(const struct device *dev, const struct sensor_trigger *trig) { if (IS_ENABLED(CONFIG_ASSERT)) { @@ -120,8 +151,11 @@ static int wakeup_int_ctrl_nolock(bool enable) * being fired before others are still not set up. */ for (size_t i = 0; (i < ARRAY_SIZE(qdec_pin)) && !err; i++) { + const struct device *port = map_gpio_port(qdec_pin[i]); + gpio_pin_t pin = map_gpio_pin(qdec_pin[i]); + if (enable) { - int val = gpio_pin_get_raw(gpio_dev, qdec_pin[i]); + int val = gpio_pin_get_raw(port, pin); if (val < 0) { LOG_ERR("Cannot read pin %zu", i); @@ -129,12 +163,11 @@ static int wakeup_int_ctrl_nolock(bool enable) continue; } - err = gpio_pin_interrupt_configure(gpio_dev, - qdec_pin[i], - val ? GPIO_INT_LEVEL_LOW : GPIO_INT_LEVEL_HIGH); + err = gpio_pin_interrupt_configure(port, pin, + val ? GPIO_INT_LEVEL_LOW : + GPIO_INT_LEVEL_HIGH); } else { - err = gpio_pin_interrupt_configure(gpio_dev, qdec_pin[i], - GPIO_INT_DISABLE); + err = gpio_pin_interrupt_configure(port, pin, GPIO_INT_DISABLE); } if (err) { @@ -183,23 +216,27 @@ static void wakeup_cb(const struct device *gpio_dev, struct gpio_callback *cb, static int setup_wakeup(void) { - int err = gpio_pin_configure(gpio_dev, - DT_PROP(DT_NODELABEL(qdec), enable_pin), - GPIO_OUTPUT); + int enable_pin = DT_PROP(QDEC_DT_NODE_ID, enable_pin); + const struct device *port = map_gpio_port(enable_pin); + gpio_pin_t pin = map_gpio_pin(enable_pin); + + int err = gpio_pin_configure(port, pin, GPIO_OUTPUT); if (err) { LOG_ERR("Cannot configure enable pin"); return err; } - err = gpio_pin_set_raw(gpio_dev, - DT_PROP(DT_NODELABEL(qdec), enable_pin), 0); + err = gpio_pin_set_raw(port, pin, 0); if (err) { LOG_ERR("Failed to set enable pin"); return err; } for (size_t i = 0; i < ARRAY_SIZE(qdec_pin); i++) { - err = gpio_pin_configure(gpio_dev, qdec_pin[i], GPIO_INPUT); + const struct device *port = map_gpio_port(qdec_pin[i]); + gpio_pin_t pin = map_gpio_pin(qdec_pin[i]); + + err = gpio_pin_configure(port, pin, GPIO_INPUT); if (err) { LOG_ERR("Cannot configure pin %zu", i); @@ -311,20 +348,23 @@ static int init(void) return -ENODEV; } - if (!device_is_ready(gpio_dev)) { - LOG_ERR("GPIO device not ready"); - return -ENODEV; - } - - BUILD_ASSERT(ARRAY_SIZE(qdec_pin) == ARRAY_SIZE(gpio_cbs), - "Invalid array size"); int err = 0; for (size_t i = 0; (i < ARRAY_SIZE(qdec_pin)) && !err; i++) { - gpio_init_callback(&gpio_cbs[i], wakeup_cb, BIT(qdec_pin[i])); - err = gpio_add_callback(gpio_dev, &gpio_cbs[i]); - if (err) { - LOG_ERR("Cannot configure cb (pin:%zu)", i); + const struct device *port = map_gpio_port(qdec_pin[i]); + gpio_pin_t pin = map_gpio_pin(qdec_pin[i]); + + if (!device_is_ready(port)) { + LOG_ERR("GPIO port %p not ready", (void *)port); + err = -ENODEV; + } + + if (!err) { + gpio_init_callback(&gpio_cbs[i], wakeup_cb, BIT(pin)); + err = gpio_add_callback(port, &gpio_cbs[i]); + if (err) { + LOG_ERR("Cannot configure cb (pin:%zu)", i); + } } } diff --git a/applications/nrf_desktop/src/modules/Kconfig.caf_ble_adv.default b/applications/nrf_desktop/src/modules/Kconfig.caf_ble_adv.default index 9186480c78f..c068e9dd96a 100644 --- a/applications/nrf_desktop/src/modules/Kconfig.caf_ble_adv.default +++ b/applications/nrf_desktop/src/modules/Kconfig.caf_ble_adv.default @@ -19,6 +19,14 @@ config DESKTOP_BLE_ADV if DESKTOP_BLE_ADV +config CAF_BLE_ADV_POWER_DOWN_ON_DISCONNECTION_REASON_0X15 + default y + help + nRF Desktop peripherals power down and suspend Bluetooth advertising + when bonded peer disconnects with reason 0x15 (Remote Device + Terminated due to Power Off) to avoid waking up the HID host until + user input is detected. + config CAF_BLE_ADV_DIRECT_ADV default n help @@ -43,6 +51,12 @@ config BT_ADV_PROV_GAP_APPEARANCE config BT_ADV_PROV_DEVICE_NAME default y +config BT_ADV_PROV_DEVICE_NAME_PAIRING_MODE_ONLY + default n + help + nRF Desktop provides device name also outside of pairing mode. This is + done for backwards compatibility. + config BT_ADV_PROV_SWIFT_PAIR default y diff --git a/applications/nrf_desktop/src/modules/Kconfig.config_channel b/applications/nrf_desktop/src/modules/Kconfig.config_channel index 6b72a034f68..b654f6b4385 100644 --- a/applications/nrf_desktop/src/modules/Kconfig.config_channel +++ b/applications/nrf_desktop/src/modules/Kconfig.config_channel @@ -58,7 +58,7 @@ config DESKTOP_CONFIG_CHANNEL_DFU_ENABLE bool "DFU over the config channel" depends on DESKTOP_CONFIG_CHANNEL_ENABLE select SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS if \ - !PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + (SOC_FLASH_NRF && !PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) help This option enables DFU over the config channel. The option automatically enables 8-bit write block size emulation to diff --git a/applications/nrf_desktop/src/modules/Kconfig.hid_state b/applications/nrf_desktop/src/modules/Kconfig.hid_state index 76934d20255..243bc80bb3c 100644 --- a/applications/nrf_desktop/src/modules/Kconfig.hid_state +++ b/applications/nrf_desktop/src/modules/Kconfig.hid_state @@ -28,6 +28,16 @@ config DESKTOP_HID_STATE_HID_KEYBOARD_LEDS_DEF_PATH Location of configuration file that holds information about LEDs associated with HID keyboard LEDs report. +config DESKTOP_HID_STATE_SUBSCRIBER_COUNT + int "Number of supported subscribers" + range 1 255 + default 1 + help + The data structures representing subscribers are statically allocated. + The number of allocated structures (specified by this Kconfig option) + must be greater than or equal to the maximum number of simultaneously + active subscribers. + config DESKTOP_HID_STATE_PM_ENABLE bool "Enable HID power manager integration" depends on CAF_POWER_MANAGER diff --git a/applications/nrf_desktop/src/modules/factory_reset.c b/applications/nrf_desktop/src/modules/factory_reset.c index 3fb9987f31d..5837c9c15ef 100644 --- a/applications/nrf_desktop/src/modules/factory_reset.c +++ b/applications/nrf_desktop/src/modules/factory_reset.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #define MODULE factory_reset diff --git a/applications/nrf_desktop/src/modules/fast_pair.c b/applications/nrf_desktop/src/modules/fast_pair.c index f95973b2c7a..40f8d3cebc4 100644 --- a/applications/nrf_desktop/src/modules/fast_pair.c +++ b/applications/nrf_desktop/src/modules/fast_pair.c @@ -129,15 +129,24 @@ static int register_app_auth_cbs(void) static bool handle_module_state_event(const struct module_state_event *event) { - if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) { - int err = register_app_auth_cbs(); + if (check_state(event, MODULE_ID(settings_loader), MODULE_STATE_READY)) { + int err; - if (!err) { - module_set_state(MODULE_STATE_READY); - } else { + err = register_app_auth_cbs(); + if (err) { LOG_ERR("Cannot register authentication callbacks (err %d)", err); module_set_state(MODULE_STATE_ERROR); + return false; } + + err = bt_fast_pair_enable(); + if (err) { + LOG_ERR("Fast Pair enable failed (err: %d)", err); + module_set_state(MODULE_STATE_ERROR); + return false; + } + + module_set_state(MODULE_STATE_READY); } return false; diff --git a/applications/nrf_desktop/src/modules/hid_state.c b/applications/nrf_desktop/src/modules/hid_state.c index cb934003a76..0e3acff6aa9 100644 --- a/applications/nrf_desktop/src/modules/hid_state.c +++ b/applications/nrf_desktop/src/modules/hid_state.c @@ -43,12 +43,7 @@ enum state { STATE_CONNECTED_BUSY /**< Connected, report is generated. */ }; -#ifndef CONFIG_USB_HID_DEVICE_COUNT - #define CONFIG_USB_HID_DEVICE_COUNT 0 -#endif - -#define SUBSCRIBER_COUNT (IS_ENABLED(CONFIG_DESKTOP_HIDS_ENABLE) + \ - CONFIG_USB_HID_DEVICE_COUNT) +#define SUBSCRIBER_COUNT CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT #define OUTPUT_REPORT_DATA_MAX_LEN (REPORT_SIZE_KEYBOARD_LEDS) @@ -829,6 +824,13 @@ static bool update_report(struct report_data *rd) { bool update_needed = false; + /* Update report is never needed for the empty report data. Empty report data does not link + * to subscriber too (`linked_rs` field is set to NULL). + */ + if (rd == &empty_rd) { + return update_needed; + } + while (!update_needed && !eventq_is_empty(&rd->eventq)) { /* There are enqueued events to handle. */ struct item_event *event = eventq_get(&rd->eventq); diff --git a/applications/serial_lte_modem/CMakeLists.txt b/applications/serial_lte_modem/CMakeLists.txt index ca06ddff73e..3d4104d72ba 100644 --- a/applications/serial_lte_modem/CMakeLists.txt +++ b/applications/serial_lte_modem/CMakeLists.txt @@ -23,9 +23,8 @@ target_sources(app PRIVATE src/slm_at_fota.c) target_sources(app PRIVATE src/slm_uart_handler.c) # NORDIC SDK APP END target_sources_ifdef(CONFIG_SLM_SMS app PRIVATE src/slm_at_sms.c) -target_sources_ifdef(CONFIG_SLM_NATIVE_TLS app PRIVATE src/slm_native_tls.c) -target_sources_ifdef(CONFIG_SLM_NATIVE_TLS app PRIVATE src/slm_at_cmng.c) target_sources_ifdef(CONFIG_SLM_PPP app PRIVATE src/slm_ppp.c) +target_sources_ifdef(CONFIG_SLM_CMUX app PRIVATE src/slm_cmux.c) add_subdirectory_ifdef(CONFIG_SLM_GNSS src/gnss) add_subdirectory_ifdef(CONFIG_SLM_NRF_CLOUD src/nrfcloud) @@ -34,6 +33,7 @@ add_subdirectory_ifdef(CONFIG_SLM_HTTPC src/http_c) add_subdirectory_ifdef(CONFIG_SLM_TWI src/twi) add_subdirectory_ifdef(CONFIG_SLM_GPIO src/gpio) add_subdirectory_ifdef(CONFIG_SLM_CARRIER src/lwm2m_carrier) +add_subdirectory_ifdef(CONFIG_SLM_NATIVE_TLS src/nativetls) if (CONFIG_SLM_FTPC OR CONFIG_SLM_TFTPC) add_subdirectory(src/ftp_c) endif() diff --git a/applications/serial_lte_modem/Kconfig b/applications/serial_lte_modem/Kconfig index 0e890a2f6a9..4f6a06dc346 100644 --- a/applications/serial_lte_modem/Kconfig +++ b/applications/serial_lte_modem/Kconfig @@ -17,9 +17,6 @@ config SLM_AT_MAX_PARAM int "Maximum number of parameters in AT command" default 42 -config SLM_NATIVE_TLS - bool "Use Zephyr mbedTLS" - # # external XTAL for UART # @@ -48,7 +45,7 @@ choice endchoice # -# UART buffers +# UART buffers (when CMUX is not in use) # config SLM_UART_RX_BUF_COUNT int "Receive buffers for UART" @@ -72,24 +69,26 @@ config SLM_UART_TX_BUF_SIZE Amount of UART traffic waiting to be sent (TX), that can be held. If the buffers are full, will send synchronously. # -# GPIO wakeup +# GPIO functionality # config SLM_START_SLEEP bool "Enter sleep on startup" help - Put nRF9160 into deep sleep mode after startup. + If enabled, the SiP is put into deep sleep when powered on. + It can then be started using SLM_POWER_PIN. -config SLM_WAKEUP_PIN - int "Wakeup pin" +config SLM_POWER_PIN + int "Power pin" default -1 help - Interface GPIO to wake up from sleep or exit idle + Interface GPIO pin used to put the SiP into deep sleep and wake up from it or exit idle. + The pin is configured with a pull up and must be pulled down shortly to perform one power off or wake up operation. config SLM_INDICATE_PIN int "Indicate pin" default -1 help - Interface GPIO pin used to indicate that data is available or an unexpected reset has occurred + Interface GPIO pin used to indicate that data is available when SLM is idle (after #XSLEEP=2 AT command). config SLM_INDICATE_TIME int "Indication period" @@ -167,6 +166,21 @@ config SLM_PPP when the LTE link (default PDN) is connected/disconnected, regardless of what is done with AT#XPPP. +config SLM_CMUX + bool "CMUX support in SLM" + +if SLM_CMUX && SLM_PPP + +config SLM_CMUX_AUTOMATIC_FALLBACK_ON_PPP_STOPPAGE + bool "AT channel automatic fallback to DLCI 1 when PPP stops." + help + This is mainly intended for compatibility with Zephyr's cellular modem driver. + If enabled, when PPP stops (which happens automatically when the LTE link goes down) + CMUX will make the AT channel be on DLCI 1. This only has an effect if it had been + configured to be elsewhere, e.g. with AT#XCMUX=2. + +endif + rsource "src/ftp_c/Kconfig" rsource "src/mqtt_c/Kconfig" rsource "src/http_c/Kconfig" @@ -174,6 +188,7 @@ rsource "src/twi/Kconfig" rsource "src/gpio/Kconfig" rsource "src/lwm2m_carrier/Kconfig" rsource "src/gnss/Kconfig" +rsource "src/nativetls/Kconfig" module = SLM module-str = serial modem diff --git a/applications/serial_lte_modem/README.rst b/applications/serial_lte_modem/README.rst index ec7f807619d..2a26690919f 100644 --- a/applications/serial_lte_modem/README.rst +++ b/applications/serial_lte_modem/README.rst @@ -8,7 +8,7 @@ The application accepts both the modem-specific AT commands and proprietary AT c The AT commands are documented in the following guides: * Modem-specific AT commands - `nRF91x1 AT Commands Reference Guide`_ and `nRF9160 AT Commands Reference Guide`_ -* Proprietary AT commands - :ref:`SLM_AT_intro` +* Proprietary AT commands - :ref:`SLM_AT_commands` See the subpages for how to use the application, how to extend it, and information on the supported AT commands. @@ -17,7 +17,8 @@ See the subpages for how to use the application, how to extend it, and informati :caption: Subpages: doc/slm_description + doc/nRF91_as_Zephyr_modem doc/slm_testing doc/slm_extending doc/slm_data_mode - doc/AT_commands_intro + doc/AT_commands diff --git a/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.conf b/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.conf new file mode 100644 index 00000000000..13159e9815f --- /dev/null +++ b/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Configuration file for nRF9131EK. +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 +CONFIG_UART_0_NRF_HW_ASYNC=y +CONFIG_SLM_POWER_PIN=28 +CONFIG_SLM_INDICATE_PIN=0 diff --git a/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.overlay b/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.overlay new file mode 100644 index 00000000000..1ff0f2d66b4 --- /dev/null +++ b/applications/serial_lte_modem/boards/nrf9131ek_nrf9131_ns.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + ncs,slm-uart = &uart0; + }; +}; + +&uart0 { + status = "okay"; + hw-flow-control; +}; diff --git a/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.conf b/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.conf new file mode 100644 index 00000000000..0a14fd6b653 --- /dev/null +++ b/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.conf @@ -0,0 +1,23 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Configuration file for nRF9151DK. +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# Use UART_0 (when working with PC terminal) +# unmask the following config +CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 +CONFIG_UART_0_NRF_HW_ASYNC=y +CONFIG_SLM_POWER_PIN=8 +CONFIG_SLM_INDICATE_PIN=0 + +# Use UART_2 (when working with external MCU) +# unmask the following config +#CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 +#CONFIG_UART_2_NRF_HW_ASYNC=y +#CONFIG_SLM_POWER_PIN=31 +#CONFIG_SLM_INDICATE_PIN=30 diff --git a/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.overlay b/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.overlay new file mode 100644 index 00000000000..ca0852e4cca --- /dev/null +++ b/applications/serial_lte_modem/boards/nrf9151dk_nrf9151_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + #include "nrf9161dk_nrf9161_ns.overlay" diff --git a/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.conf b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.conf index 38fe7bc5892..a4877579812 100644 --- a/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.conf +++ b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.conf @@ -12,12 +12,12 @@ # unmask the following config CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 CONFIG_UART_0_NRF_HW_ASYNC=y -CONFIG_SLM_WAKEUP_PIN=6 +CONFIG_SLM_POWER_PIN=6 CONFIG_SLM_INDICATE_PIN=2 # Use UART_2 (when working with external MCU) # unmask the following config #CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 #CONFIG_UART_2_NRF_HW_ASYNC=y -#CONFIG_SLM_WAKEUP_PIN=31 +#CONFIG_SLM_POWER_PIN=31 #CONFIG_SLM_INDICATE_PIN=30 diff --git a/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.overlay b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.overlay index bcc872f9d1b..9019a6d2900 100644 --- a/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.overlay +++ b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns.overlay @@ -53,10 +53,3 @@ }; }; }; - -/* Enable external flash */ -&spi3 { - mx25r64: mx25r6435f@1 { - status = "okay"; - }; -}; diff --git a/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns_0_14_0.overlay b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns_0_14_0.overlay new file mode 100644 index 00000000000..fb28105a2f1 --- /dev/null +++ b/applications/serial_lte_modem/boards/nrf9160dk_nrf9160_ns_0_14_0.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Enable external flash */ +&arduino_spi { + mx25r64: mx25r6435f@1 { + status = "okay"; + }; +}; diff --git a/applications/serial_lte_modem/boards/nrf9161dk_nrf9161_ns.conf b/applications/serial_lte_modem/boards/nrf9161dk_nrf9161_ns.conf index 7dd58f5237a..1976ebdbf4c 100644 --- a/applications/serial_lte_modem/boards/nrf9161dk_nrf9161_ns.conf +++ b/applications/serial_lte_modem/boards/nrf9161dk_nrf9161_ns.conf @@ -12,12 +12,12 @@ # unmask the following config CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 CONFIG_UART_0_NRF_HW_ASYNC=y -CONFIG_SLM_WAKEUP_PIN=8 +CONFIG_SLM_POWER_PIN=8 CONFIG_SLM_INDICATE_PIN=0 # Use UART_2 (when working with external MCU) # unmask the following config #CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 #CONFIG_UART_2_NRF_HW_ASYNC=y -#CONFIG_SLM_WAKEUP_PIN=31 +#CONFIG_SLM_POWER_PIN=31 #CONFIG_SLM_INDICATE_PIN=30 diff --git a/applications/serial_lte_modem/boards/thingy91_nrf9160_ns.conf b/applications/serial_lte_modem/boards/thingy91_nrf9160_ns.conf index 975d4d937f1..4359e6b6aff 100644 --- a/applications/serial_lte_modem/boards/thingy91_nrf9160_ns.conf +++ b/applications/serial_lte_modem/boards/thingy91_nrf9160_ns.conf @@ -11,7 +11,7 @@ # Configuration related to external sensors. CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 CONFIG_UART_0_NRF_HW_ASYNC=y -CONFIG_SLM_WAKEUP_PIN=26 +CONFIG_SLM_POWER_PIN=26 # Increase buffer space as hardware flow control is not used with Thingy:91. CONFIG_SLM_UART_RX_BUF_SIZE=2048 diff --git a/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.conf b/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.conf new file mode 100644 index 00000000000..083da28a3f2 --- /dev/null +++ b/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.conf @@ -0,0 +1,17 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Configuration file for Thingy:91 X. +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# Configuration related to external sensors. +CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 +CONFIG_UART_0_NRF_HW_ASYNC=y +CONFIG_SLM_POWER_PIN=26 + +# Increase buffer space as hardware flow control is not used with Thingy:91. +CONFIG_SLM_UART_RX_BUF_SIZE=2048 diff --git a/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.overlay b/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.overlay new file mode 100644 index 00000000000..985d94aff15 --- /dev/null +++ b/applications/serial_lte_modem/boards/thingy91x_nrf9151_ns.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + ncs,slm-uart = &uart0; + }; +}; + +&button0 { + status = "disabled"; +}; diff --git a/applications/serial_lte_modem/doc/AT_commands.rst b/applications/serial_lte_modem/doc/AT_commands.rst new file mode 100644 index 00000000000..b37ba745094 --- /dev/null +++ b/applications/serial_lte_modem/doc/AT_commands.rst @@ -0,0 +1,52 @@ +.. _SLM_AT_commands: + +SLM-specific AT commands +######################## + +The application sample uses a series of proprietary AT commands to let the nRF91 development kit operate as a Serial LTE Modem (SLM). + +The AT Commands have standardized syntax rules. + +Words enclosed in are references to syntactical elements. +Words enclosed in [square brackets] represent optional items that can be left out of the command line at the specified point. +The brackets are not used when the words appear in the command line. + +````, ```` and ```` are allowed in an AT command sent by an application. + +A string type parameter input must be enclosed between quotation marks (``"string"``). + +There are 3 types of AT commands: + +* Set command ``[=...]``. + Set commands set values or perform actions. +* Read command ``?``. + Read commands check the current values of subparameters. +* Test command ``=?``. + Test commands test the existence of the command and provide information about the type of its subparameters. + Some test commands can also have other functionality. + +AT responds to all commands with a final response. + +See the following subpages for documentation of the proprietary AT commands. +The modem-specific AT commands are documented in the `nRF91x1 AT Commands Reference Guide`_ and `nRF9160 AT Commands Reference Guide`_. + +.. toctree:: + :maxdepth: 2 + :caption: Subpages: + + Generic_AT_commands + CMUX_AT_commands + FOTA_AT_commands + FTP_AT_commands + GNSS_AT_commands + GPIO_AT_commands + HTTPC_AT_commands + ICMP_AT_commands + CARRIER_AT_commands + MQTT_AT_commands + NRFCLOUD_AT_commands + PPP_AT_commands + SMS_AT_commands + SOCKET_AT_commands + TCPUDP_AT_commands + TWI_AT_commands diff --git a/applications/serial_lte_modem/doc/AT_commands_intro.rst b/applications/serial_lte_modem/doc/AT_commands_intro.rst deleted file mode 100644 index 83c1940a729..00000000000 --- a/applications/serial_lte_modem/doc/AT_commands_intro.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _SLM_AT_intro: - -SLM-specific AT commands -######################## - -The application sample uses a series of proprietary AT commands to let the nRF91 development kit operate as a Serial LTE Modem (SLM). - -The AT Commands have standardized syntax rules. - -Words enclosed in are references to syntactical elements. -Words enclosed in [square brackets] represent optional items that can be left out of the command line at the specified point. -The brackets are not used when the words appear in the command line. - -````, ```` and ```` are allowed in an AT command sent by an application. - -A string type parameter input must be enclosed between quotation marks (``"string"``). - -There are 3 types of AT commands: - -* Set command ``[=...]``. - Set commands set values or perform actions. -* Read command ``?``. - Read commands check the current values of subparameters. -* Test command ``=?``. - Test commands test the existence of the command and provide information about the type of its subparameters. - Some test commands can also have other functionality. - -AT responds to all commands with a final response. - -See the following subpages for documentation of the proprietary AT commands. -The modem-specific AT commands are documented in the `nRF91x1 AT Commands Reference Guide`_ and `nRF9160 AT Commands Reference Guide`_. - -.. toctree:: - :maxdepth: 2 - :caption: Subpages: - - Generic_AT_commands - CARRIER_AT_commands - FOTA_AT_commands - FTP_AT_commands - GNSS_AT_commands - GPIO_AT_commands - HTTPC_AT_commands - ICMP_AT_commands - MQTT_AT_commands - NRFCLOUD_AT_commands - PPP_AT_commands - SMS_AT_commands - SOCKET_AT_commands - TCPUDP_AT_commands - TWI_AT_commands diff --git a/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst b/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst index f277546e4ee..c457b62c625 100644 --- a/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst +++ b/applications/serial_lte_modem/doc/CARRIER_AT_commands.rst @@ -79,31 +79,157 @@ Syntax The ```` command is a string, and can be used as follows: -* ``AT#XCARRIER="app_data"[,][,,]`` +* ``AT#XCARRIER="app_data_set"[,][,,]`` + + Put the value in ```` into the indicated path. + ```` must be an opaque string in double quotes, unless ``slm_data_mode`` is enabled. + + * If ```` and ```` are specified, the data is set in an instance of the Data resource (ID: 0) of the Binary App Data Container object (ID: 19). + The URI path of the resource instance is indicated as ``/19//0/``. + * If ```` and ```` are not present, the data is set in the Uplink Data resource (ID: 0) of the App Data Container object (ID: 10250). + The URI path of the resource instance is indicated as ``/10250/0/0``. + * If ```` is not present, SLM enters ``slm_data_mode`` and the data is set in the Uplink Data resource (ID: 0) of the App Data Container object (ID: 10250). + The URI path of the resource instance is indicated as ``/10250/0/0``. + * ``AT#XCARRIER="battery_level",`` + + Put the value in ```` into the Battery Level resource (ID: 9) of the Device object (ID :3). + ```` must be an integer value between ``0`` and ``100``. + * ``AT#XCARRIER="battery_status",`` + + Set the Battery Status resource (ID: 20) of the Device object (ID: 3). + ```` must be an integer value as defined in the OMA LwM2M specification. + * ``AT#XCARRIER="current",,`` + + Put the value in ```` into the Power Source Current resource (ID: 8) instance corresponding to one of the Available Power Sources resource (ID: 6) instances of the Device object (ID: 3). + Refer to the ``AT#XCARRIER="power_sources"`` command for information regarding the supported power sources. + ```` must be an integer value specified in milliamperes (mA). + * ``AT#XCARRIER="error","add|remove",`` + + Update the Error Code resource (ID: 11) of the Device Object (ID: 3) by adding or removing an individual error. + ```` must be an integer value as defined in the OMA LwM2M specification. + + * ``AT#XCARRIER="error","add",`` adds a resource instance with the indicated error if one with that error is not present already. + * ``AT#XCARRIER="error","remove",`` removes the resource instance with the indicated error if it exists. + * ``AT#XCARRIER="link_down"`` + + Request to set the modem to flight mode. + * ``AT#XCARRIER="link_up"`` + + Request to set the modem to full functionality. + * ``AT#XCARRIER="log_data",`` + + Put the value in ```` into the LogData resource (ID: 4014) of the default EventLog object (ID: 20) instance. + ```` must be an opaque string in double quotes. + * ``AT#XCARRIER="memory_free","read|write"[,]`` + + Read or write the Memory Free resource (ID: 10) of the Device object (ID: 3). + + * ``AT#XCARRIER="memory_free","read"`` returns the current value expressed in kilobytes. + * ``AT#XCARRIER="memory_free","write",`` puts the value in ```` into the resource. + ```` must be an integer value specified in kilobytes. + * ``AT#XCARRIER="memory_total",`` -* ``AT#XCARRIER="portfolio","create|read|write",[,[,]]`` + + Put the value in ```` into the Memory Total resource (ID: 21) of the Device object (ID: 3). + ```` must be an integer value specified in kilobytes. + +* ``AT#XCARRIER="portfolio","create|read|write",[,[,]]`` + + Create an instance of the Portfolio object (ID: 16), or read or write into the Identity (ID: 0) resource of the Portfolio object (ID: 16). + + * ``AT#XCARRIER="portfolio","create",`` creates an instance of the object, where the URI path is specified as ``/16/``. + * ``AT#XCARRIER="portfolio","read",,`` returns the current value of the indicated resource instance, where the URI path is specified as ``/16//0/``. + * ``AT#XCARRIER="portfolio","write",,,`` puts the value in ```` into the indicated resource instance, where the URI path is specified as ``/16//0/``. + ```` must be a string in double quotes. + * ``AT#XCARRIER="power_sources"[,[,[,...[,]]]]`` + + Set one or more sources specified in ```` parameters into the Available Power Sources resource (ID: 6) of the Device object (ID: 3). + Each ```` parameter must be an integer value as defined in the OMA LwM2M specification. + * ``AT#XCARRIER="position",,,,,`` + + Put location telemetry values into the corresponding resources of the Location object (ID: 6). + + * ```` specified in the decimal notation of latitude (WGS1984) is put into the Latitude resource (ID: 0). + Must be a double type value in double quotes. + * ```` specified in the decimal notation of latitude (WGS1984) is put into the Longitude resource (ID: 1). + Must be a double type value in double quotes. + * ```` specified in meters is put into the Altitude resource (ID: 2). + Must be a float type value in double quotes. + * ```` is put into the Timestamp resource (ID: 5). + Must be an integer value specified in UNIX time. + * ```` specified in meters is put into the Radius resource (ID: 3). + Must be a float type value in double quotes. + * ``AT#XCARRIER="reboot"`` + + Request to reboot the device. + +* ``AT#XCARRIER="send",,,[,]`` + + Perform a Send operation to send the currently stored data in the indicated resource or resource instance to the server. + This operation is currently only supported for readable opaque resources. + The URI path of the resource or resource instance is indicated as ``////``. + * ``AT#XCARRIER="time"`` + + Read the time reported by the device, including the UTC time, the UTC offset and the timezone. + See examples for response syntax. + * ``AT#XCARRIER="timezone","read|write"[,]`` + + Read or write the value reported in the Timezone (ID: 15) resource of the Device object (ID: 3) in IANA Timezone (TZ) database format. + + * ``AT#XCARRIER="timezone","read"`` returns the timezone currently stored by the device. + * ``AT#XCARRIER="timezone","write",`` puts the value in ```` into the resource. + ```` must be a string in double quotes. + * ``AT#XCARRIER="utc_offset","read|write"[,]`` + + Read or write the UTC Offset resource (ID: 14) of the Device object (ID: 3). + + * ``AT#XCARRIER="utc_offset","read"`` returns the UTC offset currently in effect for the device as per ISO 8601. + * ``AT#XCARRIER="utc_offset","write",`` puts the value in ```` into the resource. + ```` must be an integer value specified in minutes. + * ``AT#XCARRIER="utc_time","read|write"[,]`` + + Read or write the Current Time resource (ID: 13) of the Device object (ID: 3). + + * ``AT#XCARRIER="utc_time","read"`` returns the current UNIX time of the device. + * ``AT#XCARRIER="utc_time","write",`` puts the value in ```` into the resource. + ```` must be an integer value specified in UNIX time. + * ``AT#XCARRIER="velocity",,,,,`` + + Set or update the latest velocity information that will be mapped into the Velocity resource (ID: 4) and Speed resource (ID: 6) of the Location object (ID: 6). + + * ```` is the horizontal direction of movement in degrees clockwise from North. + Must be an integer value between ``0`` and ``359``. + * ```` is the horizontal non-negative speed in meters per second. + Must be a float type value in double quotes. + * ```` is the vertical speed in meters per second. + A positive value indicates upward motion, while a negative value indicates downward motion. + Must be a float type value in double quotes. + * ```` is the horizontal uncertainty speed in meters per second. + Must be a non-negative float type value in double quotes. + * ```` is the vertical uncertainty speed in meters per second. + Must be a non-negative float type value in double quotes. + * ``AT#XCARRIER="voltage",,`` -The values of the parameters depend on the command string used. -Specifying ``instance_id`` and ``resource_instance_id`` in the ``app_data`` command sends the data to the Binary App Data Container object instead of the App Data Container object. -When using the ``app_data`` command, if no attributes are specified, SLM enters ``slm_data_mode``. -``slm_data_mode`` is only supported when using the App Data Container object. + Put the value in ```` into the Power Source Voltage resource (ID: 7) instance corresponding to one of the Available Power Sources resource (ID: 6) instances of the Device object (ID: 3). + Refer to the ``AT#XCARRIER="power_sources"`` command for information regarding the supported power sources. + ```` must be an integer value specified in millivolts. Response syntax ~~~~~~~~~~~~~~~ @@ -143,6 +269,16 @@ Examples AT#XCARRIER="reboot" OK +:: + + AT#XCARRIER="position","63.43","10.47","48",1708684683,"30.5" + OK + +:: + + AT#XCARRIER="send",19,0,0,0 + OK + Read command ------------ @@ -179,24 +315,48 @@ The ```` command is a string, and can be used as follows: * ``AT#XCARRIERCFG="apn"[,]`` + Configure the LwM2M carrier library to use a custom APN specified in ```` when connecting to the device management network. + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_APN` Kconfig option. * ``AT#XCARRIERCFG="auto_startup"[,<0|1>]`` - Set flag to automatically apply the enabled settings to the library configuration and connect to the device management server. + Set a flag to automatically apply the enabled settings to the LwM2M carrier library configuration and connect to the device management network. + This command accepts two possible input parameters: ``0`` to disable or ``1`` to enable. * ``AT#XCARRIERCFG="bootstrap_smartcard"[,<0|1>]`` + Configure the LwM2M carrier library to allow bootstrap from Smartcard. + This command accepts two possible input parameters: ``0`` to disable or ``1`` to enable. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_BOOTSTRAP_SMARTCARD` Kconfig option. -* ``AT#XCARRIERCFG="carriers"[,"all"|[[,...[,]]]]`` +* ``AT#XCARRIERCFG="carriers"[,"all"|[,[,...[,]]]]`` - Choose the networks in which the LwM2M carrier library will apply (see the :ref:`general_options_lwm2m` section of the library's documentation). + Configure the networks in which the LwM2M carrier library will apply (see the :ref:`general_options_lwm2m` section of the library's documentation). + By default, any network is allowed. The input parameters are mapped as follows: + + * ``all`` - Any network allowed. + * ``0`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`. + * ``1`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`. + * ``2`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_ATT`. + * ``3`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`. + * ``4`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`. + * ``5`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`. * ``AT#XCARRIERCFG="coap_con_interval"[,]`` + Configure how often the LwM2M carrier library is to send the Notify operation as a CoAP Confirmable message instead of a Non-Confirmable message. + ```` must be an integer value specified in seconds. + Two special values may also be used: ``-1`` to always use Confirmable notifications, or ``0`` to use the default interval of 86400 seconds. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_COAP_CON_INTERVAL` Kconfig option. +* ``AT#XCARRIERCFG="download_timeout"[,]`` + + Configure the time allowed for a single firmware image download before it is aborted. + This configuration is only supported for Push delivery method of firmware images. + ```` must be an integer value specified in minutes. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT` Kconfig option. + * ``AT#XCARRIERCFG="config_enable"[,<0|1>]`` Set flag to apply the stored settings to the general Kconfig options (see the :ref:`general_options_lwm2m` section of the library's documentation). @@ -207,38 +367,80 @@ The ```` command is a string, and can be used as follows: * ``AT#XCARRIERCFG="device_type"[,]`` + Configure the value in ```` to be put into the Device Type resource (ID: 17) of the Device object (ID: 3). + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_TYPE` Kconfig option. * ``AT#XCARRIERCFG="hardware_version"[,]`` + Configure the value in ```` to be put into the Hardware Version resource (ID: 18) of the Device object (ID: 3). + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_HARDWARE_VERSION` Kconfig option. * ``AT#XCARRIERCFG="manufacturer"[,]`` + Configure the value in ```` to be put into the Manufacturer resource (ID: 0) of the Device object (ID: 3). + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_MANUFACTURER` Kconfig option. * ``AT#XCARRIERCFG="model_number"[,]`` + Configure the value in ```` to be put into the Model Number resource (ID: 1) of the Device object (ID: 3). + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_MODEL_NUMBER` Kconfig option. * ``AT#XCARRIERCFG="software_version"[,]`` + Configure the value in ```` to be put into the Software Version resource (ID: 19) of the Device object (ID: 3). + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_SOFTWARE_VERSION` Kconfig option. * ``AT#XCARRIERCFG="device_serial_no_type"[,]`` + Configure the Device Serial Number type to be used in LG U+ network. + The ```` must be an integer value. + It accepts the following values: + + * ``0`` - :kconfig:option:`LWM2M_CARRIER_LG_UPLUS_IMEI`. + * ``1`` - :kconfig:option:`LWM2M_CARRIER_LG_UPLUS_2DID`. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS_DEVICE_SERIAL_NUMBER` Kconfig option. * ``AT#XCARRIERCFG="service_code"[,]`` + Configure the Service Code registered for this device with LG U+. + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS_SERVICE_CODE` Kconfig option. * ``AT#XCARRIERCFG="pdn_type"[,]`` + Configure the PDN type of the custom APN configured through the ``AT#XCARRIERCFG="apn"`` command. + ```` must be an integer value. + It accepts the following values: + + * ``0`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV4V6`. + * ``1`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV4`. + * ``2`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV6`. + * ``3`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_NONIP`. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_PDN_TYPE` Kconfig option. +* ``AT#XCARRIERCFG="queue_mode"[,<0|1>]`` + + Configure whether the LwM2M carrier library is to inform the server that it may be disconnected for an extended period of time. + This configuration corresponds to the Queue Mode Operation as defined in the OMA LwM2M specification. + This command accepts two possible input parameters: ``0`` to disable or ``1`` to enable. + For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_QUEUE_MODE` Kconfig option. + * ``AT#XCARRIERCFG="binding"[,]`` + Configure the binding over which the LwM2M carrier library is to connect to the device management network. + ```` must be a string in double quotes. + It accepts the following values: + + * ``"U"`` - :kconfig:option:`LWM2M_CARRIER_SERVER_BINDING_U`. + * ``"N"`` - :kconfig:option:`LWM2M_CARRIER_SERVER_BINDING_N`. + For details, see the :kconfig:option:`CONFIG_LWM2M_SERVER_BINDING_CHOICE` Kconfig option. * ``AT#XCARRIERCFG="server_enable"[,<0|1>]`` @@ -247,56 +449,39 @@ The ```` command is a string, and can be used as follows: * ``AT#XCARRIERCFG="is_bootstrap"[,<0|1>]`` + Indicate whether the custom server configured through the ``AT#XCARRIERCFG="uri"`` command is a bootstrap server. + This command accepts two possible input parameters: ``0`` if it is not a bootstrap server or ``1`` if it is a bootstrap server. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_IS_BOOTSTRAP_SERVER` Kconfig option. * ``AT#XCARRIERCFG="lifetime"[,]`` + Configure the lifetime of the custom server configured through the ``AT#XCARRIERCFG="uri"`` command. + ```` must an integer value specified in seconds. + This configuration is ignored if the custom server is a bootstrap server. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_LIFETIME` Kconfig option. * ``AT#XCARRIERCFG="sec_tag"[,]`` + Configure the security tag that stores the credentials to be used to set up the DTLS session with the custom server configured through the ``AT#XCARRIERCFG="uri"`` command. + ```` must be an integer value specifying the security tag number to be used. + This configuration is ignored for non-secure connections. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_SEC_TAG` Kconfig option. * ``AT#XCARRIERCFG="uri"[,]`` + Configure the URI of a custom server that the library is to connect to. + ```` must be a string in double quotes. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_URI` Kconfig option. * ``AT#XCARRIERCFG="session_idle_timeout"[,]`` + Configure how long a DTLS session used by the library can be idle before it is closed. + ```` must be an integer value specified in seconds. + Two special values may also be used: ``-1`` to disable the session idle timeout, or ``0`` to use the default interval of 60 seconds. For details, see the :kconfig:option:`CONFIG_LWM2M_CARRIER_SESSION_IDLE_TIMEOUT` Kconfig option. -The values of the parameters depend on the command string used. If a valid command string is used without any parameter, the current value of the corresponding configuration will be returned in the response, as in the examples shown below. -Boolean configurations, such as ``auto_startup`` or ``is_bootstrap``, only accept ``0`` (disable) and ``1`` (enable) as input parameters. - -The ``carriers`` configuration allows to choose the networks in which the LwM2M carrier library will apply. -Possible inputs are mapped as follows: - -* ``all`` - Any network allowed. -* ``0`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`. -* ``1`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`. -* ``2`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_ATT`. -* ``3`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`. -* ``4`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`. -* ``5`` - :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`. - -The ``device_serial_no_type`` configuration accepts the following values: - -* ``0`` - :kconfig:option:`LWM2M_CARRIER_LG_UPLUS_IMEI`. -* ``1`` - :kconfig:option:`LWM2M_CARRIER_LG_UPLUS_2DID`. - -The ``pdn_type`` configuration accepts the following values: - -* ``0`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV4V6`. -* ``1`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV4`. -* ``2`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_IPV6`. -* ``3`` - :c:macro:`LWM2M_CARRIER_PDN_TYPE_NONIP`. - -The ``binding`` configuration accepts the following values: - -* ``"U"`` - :kconfig:option:`LWM2M_CARRIER_SERVER_BINDING_U`. -* ``"N"`` - :kconfig:option:`LWM2M_CARRIER_SERVER_BINDING_N`. Response syntax ~~~~~~~~~~~~~~~ @@ -328,6 +513,15 @@ Examples #XCARRIERCFG: Nordic Semiconductor ASA OK +:: + + AT#XCARRIERCFG="apn","custom.APN" + OK + + AT#XCARRIERCFG="apn" + #XCARRIERCFG: custom.APN + OK + :: AT#XCARRIERCFG="carriers","all" diff --git a/applications/serial_lte_modem/doc/CMUX_AT_commands.rst b/applications/serial_lte_modem/doc/CMUX_AT_commands.rst new file mode 100644 index 00000000000..6246fa99fbb --- /dev/null +++ b/applications/serial_lte_modem/doc/CMUX_AT_commands.rst @@ -0,0 +1,143 @@ +.. _SLM_AT_CMUX: + +CMUX AT commands +**************** + +.. contents:: + :local: + :depth: 2 + +This page describes CMUX-related AT commands. + +The CMUX protocol enables multiplexing multiple data streams through a single serial link, setting up one channel per data stream. +For example, it can be used to exchange AT data and have a :ref:`Point-to-Point Protocol (PPP) ` link up at the same time on a single UART. + +.. note:: + + To use the nRF91 Series SiP as a standalone modem in Zephyr, see :ref:`slm_as_zephyr_modem`. + +CMUX is enabled in SLM by compiling it with the appropriate configuration files, depending on your use case. +See the :ref:`slm_config_files` section for more information. + +.. slm_cmux_baud_rate_note_start + +.. note:: + + The maximum recommended baud rate is 460 800. + At higher baud rates (921 600, 1 000 000), it is possible for bytes to come in faster than the chip is able to handle, which causes the buffer space to run out if it goes on for too long. + UART RX is not disabled in that case, which results in data loss and communication failures. + + At a baud rate of 460 800, the maximum throughput is slightly below that of the nRF91 Series modem when using LTE-M. + +.. slm_cmux_baud_rate_note_end + +.. note:: + + SLM does not have an equivalent to the ``AT+CMUX`` command described in 3GPP TS 27.007. + Here is how SLM's implementation of CMUX relates to the standard command's parameters: + + * Only UIH frames are used. + * The speed used is the configured baud rate of SLM's UART. + * The maximum frame size is ``2100`` (defined by :c:macro:`SLM_AT_MAX_RSP_LEN` found in :file:`slm_defines.h`). + +CMUX setup #XCMUX +================= + +The ``#XCMUX`` command manages the configuration of CMUX over the serial link. + +Set command +----------- + +The set command allows you to start CMUX and assign the CMUX channels. + +Syntax +~~~~~~ + +:: + + AT#XCMUX[=] + +The ```` parameter is an integer used to indicate the address of the AT channel. +If specified, it must be between 1 and the total number of channels. +The AT channel denotes the CMUX channel where AT data (commands, responses, notifications) is exchanged. +If not specified, the previously used address is used. +If no address has been previously specified, the default address is 1. + +.. note:: + + If there is more than one CMUX channel (such as when using :ref:`PPP `), the non-AT channels will automatically get assigned to addresses other than the one used for the AT channel. + For example, if PPP is enabled and CMUX is started with the ``AT#XCMUX=2`` command, the AT channel will be assigned to address 2 and the PPP channel to address 1. + +An ``OK`` response is sent if the command is accepted, after which CMUX is started. +This means that after successfully running this command, you must set up the CMUX link and open the channels appropriately. +The AT channel will be available at the configured address. +You can send an empty ``AT`` command to make sure that the protocol is set up properly. + +.. note:: + + This command can be run when CMUX is already running to change the address of the AT channel. + However, this is not allowed when PPP is running. + +Read command +------------ + +The read command allows you to read the address of the AT channel and the total number of channels. + +Syntax +~~~~~~ + +:: + + AT#XCMUX? + +Response syntax +~~~~~~~~~~~~~~~ + +:: + + #XCMUX: , + +* The ```` parameter indicates the address of the AT channel. + It is between 1 and ````. +* The ```` parameter is the total number of CMUX channels. + It depends on what features are enabled (for example, :ref:`PPP `). + +Example +------- + +Without PPP: + +:: + + AT#XCMUX? + + #XCMUX: 1,1 + + OK + AT#XCMUX + + OK + // Here, CMUX is started and communication can now happen only through it (until a reset). + // Open the AT channel, which is the only one, to continue exchanging AT data. + AT + + OK + +With PPP: + +:: + + AT#XCMUX? + + #XCMUX: 1,2 + + OK + AT#XCMUX=2 + + OK + // Start up CMUX and open the channels. The AT channel is now at address 2. + AT#XCMUX? + + #XCMUX: 2,2 + + OK diff --git a/applications/serial_lte_modem/doc/FOTA_AT_commands.rst b/applications/serial_lte_modem/doc/FOTA_AT_commands.rst index 71ce010b1d8..1ca4e9a38e5 100644 --- a/applications/serial_lte_modem/doc/FOTA_AT_commands.rst +++ b/applications/serial_lte_modem/doc/FOTA_AT_commands.rst @@ -35,7 +35,8 @@ Syntax * ``3`` - Start FOTA for full modem update. Can only be used when the :file:`overlay-full_fota.conf` configuration file is used. - Not supported on the :ref:`Thingy:91 ` as it lacks an external flash to store the firmware image. + Not supported on the :ref:`Thingy:91 ` or nRF9160 DK board revisions older than 0.14.0 as they lack an external flash to store the firmware image. + See :ref:`nrf9160_board_revisions` for more details. * ``7`` - Read modem DFU area size and firmware image offset (for modem delta update). * ``9`` - Erase modem DFU area (for modem delta update). diff --git a/applications/serial_lte_modem/doc/GNSS_AT_commands.rst b/applications/serial_lte_modem/doc/GNSS_AT_commands.rst index 9ac97b0fea9..f66483b6a3c 100644 --- a/applications/serial_lte_modem/doc/GNSS_AT_commands.rst +++ b/applications/serial_lte_modem/doc/GNSS_AT_commands.rst @@ -115,7 +115,7 @@ Unsolicited notification * The ```` value represents the heading of the movement of the user in degrees. * The ```` value represents the UTC date-time. -.. gps_status_notif_start +.. slm_gps_status_notif_start .. code-block:: @@ -133,7 +133,7 @@ Unsolicited notification * ``3`` - GNSS enters sleep because of timeout. * ``4`` - GNSS enters sleep because a fix is acquired. -.. gps_status_notif_end +.. slm_gps_status_notif_end Example ~~~~~~~ @@ -265,8 +265,8 @@ Response syntax ~~~~~~~~~~~~~~~ .. include:: GNSS_AT_commands.rst - :start-after: gps_status_notif_start - :end-before: gps_status_notif_end + :start-after: slm_gps_status_notif_start + :end-before: slm_gps_status_notif_end Example ~~~~~~~ diff --git a/applications/serial_lte_modem/doc/Generic_AT_commands.rst b/applications/serial_lte_modem/doc/Generic_AT_commands.rst index 2b6b172c023..7b8ee9f98c3 100644 --- a/applications/serial_lte_modem/doc/Generic_AT_commands.rst +++ b/applications/serial_lte_modem/doc/Generic_AT_commands.rst @@ -146,15 +146,15 @@ The ```` parameter accepts only the following integer values: * ``1`` - Enter Sleep. In this mode, both the SLM service and the LTE connection are terminated. - The nRF91 Series SiP can be woken up using the :ref:`CONFIG_SLM_WAKEUP_PIN `. + The nRF91 Series SiP can be woken up using the pin specified with the :ref:`CONFIG_SLM_POWER_PIN ` Kconfig option. * ``2`` - Enter Idle. - In this mode, both the SLM service and the LTE connection are maintained. - The nRF91 Series SiP can be made to exit idle using the :ref:`CONFIG_SLM_WAKEUP_PIN `. - If the :ref:`CONFIG_SLM_INDICATE_PIN ` is defined, SLM toggle this GPIO when there is data for MCU. - MCU could in turn make SLM to exit idle by :ref:`CONFIG_SLM_WAKEUP_PIN `. - The data is buffered during the idle status and sent to MCU after exiting the idle status. + + The nRF91 Series SiP can be made to exit idle using the pin specified with the :ref:`CONFIG_SLM_POWER_PIN ` Kconfig option. + If the :ref:`CONFIG_SLM_INDICATE_PIN ` Kconfig option is defined, SLM toggles the specified pin when there is data for the MCU to read. + The MCU can in turn make SLM exit idle by toggling the pin specified with the :ref:`CONFIG_SLM_POWER_PIN ` Kconfig option. + The data is buffered when SLM is idle and sent to the MCU after having exited idle. .. note:: @@ -240,7 +240,7 @@ Syntax .. note:: - In this case the nRF91 Series SiP cannot be woken up using the :ref:`CONFIG_SLM_WAKEUP_PIN `.. + In this case the nRF91 Series SiP cannot be woken up using the pin specified with the :ref:`CONFIG_SLM_POWER_PIN ` Kconfig option. Example ~~~~~~~~ @@ -405,51 +405,52 @@ The test command is not supported. Native TLS CMNG #XCMNG ====================== -The ``#XCMNG`` command manages the credentials to support :ref:`CONFIG_SLM_NATIVE_TLS `. -This command is similar to the modem ``%CMNG`` command. +The ``#XCMNG`` command manages the credentials to support :ref:`CONFIG_SLM_NATIVE_TLS `, which is activated with the :file:`overlay-native_tls.conf` configuration file. +This command is similar to the modem ``%CMNG`` command, but it utilizes Zephyr setting storage instead of modem credential storage. + +.. note:: + + The Zephyr setting storage is unencrypted and accessible through the debug port of the nRF91 Series devices. Set command ----------- The set command is used for credential storage management. -The command writes, reads, deletes, and checks the existence of keys and certificates. +The command writes and deletes credentials. +It can also list the ``sec_tag`` and ``type`` values of existing credentials. Syntax ~~~~~~ -The following is the syntax when :ref:`CONFIG_SLM_NATIVE_TLS ` is selected: :: - #XCMNG=[,[,[,]]] + #XCMNG=[,[,[,]]] -The ```` parameter is an integer. -It accepts the following values: +The ```` parameter can have the following integer values: * ``0`` - Write a credential. -* ``1`` - List credentials (currently not supported). -* ``2`` - Read a credential (currently not supported). +* ``1`` - List credentials. * ``3`` - Delete a credential. -The ```` parameter is an integer ranging between ``0`` and ``2147483647``. -It is mandatory for *write*, *read*, and *delete* operations. -It is optional for *list* operations. +The ```` parameter can have an integer value ranging between ``0`` and ``2147483647``. +It is mandatory for *write* and *delete* operations. -The ```` parameter is an integer. -It accepts the following values: +The ```` parameter can have the following integer values: -* ``0`` - Root CA certificate (ASCII text) -* ``1`` - Certificate (ASCII text) -* ``2`` - Private key (ASCII text) +* ``0`` - Root CA certificate (PEM format) +* ``1`` - Certificate (PEM format) +* ``2`` - Private key (PEM format) +* ``3`` - Pre-shared key (PSK) (ASCII text) +* ``4`` - PSK identity (ASCII text) -The ```` parameter is a string. -It is mandatory if ```` is ``0`` (write a credential). -It is the content of a Privacy Enhanced Mail (PEM) file enclosed in double quotes (X.509 PEM entities). -An empty string is not allowed. +It is mandatory for *write* and *delete* operations. -Response syntax -~~~~~~~~~~~~~~~ +The ```` parameter can have the following string values: + +* The credential in Privacy Enhanced Mail (PEM) format when ```` has a value of ``0``, ``1`` or ``2``. +* The credential in ASCII text when ```` has a value of ``3`` or ``4``. -There is no response. +It is mandatory for *write* operations. Example ~~~~~~~ @@ -476,6 +477,26 @@ Example OK + AT#XCMNG=0,11,3,"PSK" + + OK + + AT#XCMNG=0,11,4,"Identity" + + OK + + AT#XCMNG=1 + + #XCMNG: 11,4 + #XCMNG: 11,3 + #XCMNG: 10,0 + + OK + + AT#XCMNG=3,10,0 + + OK + Read command ------------ diff --git a/applications/serial_lte_modem/doc/HTTPC_AT_commands.rst b/applications/serial_lte_modem/doc/HTTPC_AT_commands.rst index 84a5a165d6b..85043f2b1e4 100644 --- a/applications/serial_lte_modem/doc/HTTPC_AT_commands.rst +++ b/applications/serial_lte_modem/doc/HTTPC_AT_commands.rst @@ -52,7 +52,7 @@ Syntax * ``0`` - Do not verify the hostname against the received certificate. * ``1`` - Verify the hostname against the received certificate (default). -See `nRF socket options`_ ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. +See :ref:`nRF socket options ` ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. Response syntax diff --git a/applications/serial_lte_modem/doc/MQTT_AT_commands.rst b/applications/serial_lte_modem/doc/MQTT_AT_commands.rst index 139221549d3..4ceacafcccc 100644 --- a/applications/serial_lte_modem/doc/MQTT_AT_commands.rst +++ b/applications/serial_lte_modem/doc/MQTT_AT_commands.rst @@ -9,44 +9,11 @@ MQTT client AT commands This page describes the AT commands used to operate the MQTT client. -MQTT event #XMQTTEVT -==================== +.. note:: -The ``#XMQTTEVT`` is an unsolicited notification that indicates the event of the MQTT client. - -Unsolicited notification ------------------------- - -It indicates the event of the MQTT client. - -Syntax -~~~~~~ - -:: - - #XMQTTEVT=, - -* The ```` value is an integer indicating the type of the event. - It can return the following values: - - * ``0`` - Connection request. - * ``1`` - Disconnection. - The MQTT client is disconnected from the MQTT broker once this event is notified. - * ``2`` - Message received on a topic the client is subscribed to. - * ``3`` - Acknowledgment for the published message with QoS 1. - * ``4`` - Confirmation of the reception for the published message with QoS 2. - * ``5`` - Release of the published message with QoS 2. - * ``6`` - Confirmation to a publish release message with QoS 2. - * ``7`` - Reception of the subscribe request. - * ``8`` - Reception of the unsubscription request. - * ``9`` - Ping response from the MQTT broker. - -* The ```` value is an integer indicating the result of the event. - It can return the following values: - - * ``0`` - Success. - * *Negative value* - Failure. - It is the error code indicating the reason for the failure. + The MQTT client holds no internal state information for publish and subscript. + It will not retransmit packets or guarantee packet delivery according to QoS classes. + This deviates from MQTT v3.1.1. MQTT configure #XMQTTCFG ======================== @@ -179,9 +146,9 @@ Syntax * ``2`` - Connect to the MQTT broker using IP protocol family version 6. * The ```` parameter is a string. - It indicates the MQTT Client username. + It indicates the MQTT client username. * The ```` parameter is a string. - It indicates the MQTT Client password in cleartext. + It indicates the MQTT client password in cleartext. * The ```` parameter is a string. It indicates the MQTT broker hostname. * The ```` parameter is an unsigned 16-bit integer (0 - 65535). @@ -194,16 +161,35 @@ Response syntax :: - #XMQTTEVT: , + #XMQTTEVT=, -* The ```` value is an integer. - When ``0``, it indicates the acknowledgment of the connection request. -* The ```` value is an integer. - It can return the following values: +* The ```` value is an integer indicating the type of the event. + It can return the following values for the ``#XMQTTCON`` command: + + * ``0`` - Acknowledgment of connection request (CONNACK). + * ``1`` - Disconnection notification (DISCONNECT). + The MQTT client is disconnected from the MQTT broker once this event is notified. + +* The ```` value is an integer. It can return the following values: + + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. + + +Unsolicited notification +------------------------ + +:: + #XMQTTEVT=, - * ``0`` - Connection succeeded. - * *Negative Value* - Error code. - It indicates the reason for the failure. +* The ```` value is an integer indicating the type of the event. + After the connection is established, it can return ``9`` to indicate a ping response from the MQTT broker (PINGRESP). + This is received when pinging (PINGREQ) the broker after the keep alive is reached. + +* The ```` value is an integer. It can return the following values: + + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. Examples ~~~~~~~~ @@ -217,6 +203,9 @@ Examples OK #XMQTTEVT: 0,0 + Keep alive expires and broker responds to our ping: + #XMQTTEVT: 9,0 + :: AT#XMQTTCON=0 @@ -313,9 +302,9 @@ Syntax AT#XMQTTSUB=, * The ```` parameter is a string. - It indicates the topic to be subscribed to. + It indicates the topic to subscribe to. * The ```` parameter is an integer. - It indicates the MQTT Quality of Service types. + It indicates the MQTT Quality of Service type to use. It can accept the following values: * ``0`` - Lowest Quality of Service. @@ -333,26 +322,24 @@ Response syntax #XMQTTEVT: , * The ```` value is an integer. - It can return the following values: + It can return the following values for the ``#XMQTTSUB`` command:: - * ``2`` - Notification that a *publish event* has been received on a topic the client is subscribed to. - * ``7`` - Acknowledgment of the subscribe request. + * ``7`` - Acknowledgment of the subscribe request (SUBACK). -* The ```` value is an integer. - It can return the following values: +* The ```` value is an integer. It can return the following values: - * ``0`` - Value indicating the acknowledgment of the connection request. - * *Negative Value* - Error code indicating the reason for the failure. + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. -Unsolicited notification -~~~~~~~~~~~~~~~~~~~~~~~~ +Unsolicited notifications +~~~~~~~~~~~~~~~~~~~~~~~~~ -If the MQTT client successfully subscribes to a topic, the following unsolicited notification indicates that a message from the topic is received: +When the MQTT client has successfully subscribed to a topic and a message is published with the topic, the following unsolicited notifications are received: :: - #XMQTTMSG: , - + #XMQTTMSG: , + * The ```` value is an integer. @@ -360,9 +347,24 @@ If the MQTT client successfully subscribes to a topic, the following unsolicited * The ```` parameter is an integer. It indicates the length of the ```` field. * The ```` value is a string. - It indicates the topic that receives the message. + It indicates the topic that received the message. * The ```` value can be a string or a HEX. - It contains the message received from a topic. + It contains the message received from the topic. + +:: + + #XMQTTEVT: , + +* The ```` value is an integer. + It can return the following values for the ``#XMQTTSUB`` command: + + * ``2`` - Message received on a topic the client is subscribed to (PUBLISH). + * ``5`` - Release of a published message with QoS 2 (PUBREL). + +* The ```` value is an integer. It can return the following values: + + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. Examples @@ -374,18 +376,40 @@ Examples OK #XMQTTEVT: 7,0 + Message with QoS0 is received: + #XMQTTMSG: 21,7 + nrf91/slm/mqtt/topic0 + message + #XMQTTEVT: 2,0 + :: AT#XMQTTSUB="nrf91/slm/mqtt/topic1",1 OK #XMQTTEVT: 7,0 + Message with QoS1 is received: + #XMQTTMSG: 21,7 + nrf91/slm/mqtt/topic1 + message + + #XMQTTEVT: 2,0 + :: AT#XMQTTSUB="nrf91/slm/mqtt/topic2",2 OK #XMQTTEVT: 7,0 + Message with QoS2 is received: + #XMQTTMSG: 21,7 + nrf91/slm/mqtt/topic2 + message + + #XMQTTEVT: 2,0 + + #XMQTTEVT: 5,0 + Read command ------------ @@ -425,13 +449,12 @@ Response syntax #XMQTTEVT: , * The ```` value is an integer. - When ``8``, it acknowledges the reception of the unsubscription request. + It can return ``8`` for the ``#XMQTTUNSUB`` command to indicate an acknowledgment of the unsubscription request (UNSUBACK). -* The ```` value is an integer. - It can return the following values: +* The ```` value is an integer. It can return the following values: - * ``0`` - Value indicating the successful unsubscription. - * *Negative Value* - Error code indicating the reason for the failure. + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. Examples ~~~~~~~~ @@ -478,7 +501,7 @@ Syntax The maximum size of the payload is 1024 bytes when not empty. If the payload is empty (for example, ``""``), SLM enters ``slm_data_mode``. * The ```` parameter is an integer. - It indicates the MQTT Quality of Service types. + It indicates the MQTT Quality of Service type to use. It can accept the following values: * ``0`` - Lowest Quality of Service (default value). @@ -500,22 +523,16 @@ Response syntax #XMQTTEVT: , * The ```` value is an integer. - It can return the following values: - - * ``3`` - Acknowledgment for the published message with QoS 1. - * ``4`` - Reception confirmation for the published message with QoS 2. - - It is notified when PUBREC is received from the broker. - * ``5`` - Release of the published message with QoS 2. - * ``6`` - Confirmation (PUBREL) to a publish release message with QoS 2. + It can return the following values for the ``#XMQTTPUB`` command: - It is notified when PUBREL is received from the broker. + * ``3`` - Acknowledgment for the published message with QoS 1 (PUBACK). + * ``4`` - Reception confirmation for the published message with QoS 2 (PUBREC). + * ``6`` - Confirmation to a publish release message with QoS 2 (PUBCOMP). -* The ```` value is an integer. - It can return the following values: +* The ```` value is an integer. It can return the following values: - * ``0`` - Value indicating the acknowledgment of the connection request. - * *Negative Value* - Error code indicating the reason for the failure. + * ``0`` - Success. + * *Negative value* - Error code indicating the reason for the failure. Examples ~~~~~~~~ @@ -524,10 +541,6 @@ Examples AT#XMQTTPUB="nrf91/slm/mqtt/topic0","Test message with QoS 0",0,0 OK - #XMQTTMSG: 21,23 - nrf91/slm/mqtt/topic0 - Test message with QoS 0 - #XMQTTEVT: 2,0 :: @@ -535,20 +548,12 @@ Examples OK {"msg":"Test Json publish"}+++ #XDATAMODE: 0 - #XMQTTMSG: 21,27 - nrf91/slm/mqtt/topic0 - {"msg":"Test Json publish"} - #XMQTTEVT: 2,0 :: AT#XMQTTPUB="nrf91/slm/mqtt/topic1","Test message with QoS 1",1,0 OK #XMQTTEVT: 3,0 - #XMQTTMSG: 21,23 - nrf91/slm/mqtt/topic1 - Test message with QoS 1 - #XMQTTEVT: 2,0 :: @@ -558,10 +563,6 @@ Examples #XDATAMODE: 0 #XMQTTEVT: 4,0 #XMQTTEVT: 6,0 - #XMQTTMSG: 21,23 - nrf91/slm/mqtt/topic2 - Test message with QoS 2 - #XMQTTEVT: 2,0 Read command ------------ diff --git a/applications/serial_lte_modem/doc/PPP_AT_commands.rst b/applications/serial_lte_modem/doc/PPP_AT_commands.rst index 54a1b30bdde..8cc534995bb 100644 --- a/applications/serial_lte_modem/doc/PPP_AT_commands.rst +++ b/applications/serial_lte_modem/doc/PPP_AT_commands.rst @@ -7,7 +7,19 @@ PPP AT commands :local: :depth: 2 -This page describes PPP-related AT commands. +This page describes AT commands related to the Point-to-Point Protocol (PPP). + +.. note:: + + To use the nRF91 Series SiP as a standalone modem in Zephyr, see :ref:`slm_as_zephyr_modem`. + +PPP is enabled in SLM by compiling it with the appropriate configuration files, depending on your use case (with or without CMUX). +See the :ref:`slm_config_files` section for more information. + +.. note:: + + If :ref:`CMUX ` is enabled, PPP is usable only through a CMUX channel. + In that case, the CMUX link should be set up before PPP is started. Control PPP #XPPP ================= @@ -17,6 +29,11 @@ Set command The set command allows you to start and stop PPP. +.. note:: + + PPP is automatically started and stopped by SLM when the default PDN connection is established and lost, respectively. + This happens even if PPP has previously been stopped or started with this command. + Syntax ~~~~~~ @@ -28,12 +45,6 @@ Syntax * ``0`` - Stop PPP. * ``1`` - Start PPP. - If PPP is already started, it is first stopped before being started again. - -.. note:: - - PPP is automatically started and stopped when the default PDN connection is established and lost, respectively. - This happens even if PPP has previously been stopped or started with this command. Read command ------------ @@ -45,7 +56,7 @@ Syntax :: - #XPPP? + AT#XPPP? Response syntax ~~~~~~~~~~~~~~~ @@ -60,11 +71,6 @@ Response syntax * The ```` parameter is an integer that indicates whether a peer is connected to PPP. It is ``1`` for connected or ``0`` for not connected. -Test command ------------- - -The test command is not supported. - Example ------- @@ -93,3 +99,40 @@ Example #XPPP: 0,0 OK + +Testing on Linux +================ + +You can test SLM's PPP on Linux by using the ``pppd`` command, though SLM must be compiled without CMUX because there is no widely available utility that allows multiplexing a device file on Linux. + +.. note:: + + If you have a utility that allows multiplexing a device file on Linux, you can use SLM's PPP with the ``pppd`` command through CMUX. + To do this, you must first set up the CMUX link. + Then, make sure to replace the device file argument in the ``pppd`` command with that of SLM's PPP channel, which will have been created by the CMUX utility. + See :ref:`SLM_AT_CMUX` for more information on SLM's CMUX. + +For the process described here, SLM's UARTs must be connected to the Linux host. + +1. Get PPP running on SLM. + To do this, start SLM and issue an ``AT+CFUN=1`` command. +#. Make sure that the network registration succeeds and that PPP is started successfully. + To do this, either look at SLM's logs, or issue an ``AT#XPPP?`` command, which returns ``#XPPP: 1,0`` when PPP has started successfully. +#. Run the following command on the Linux host: + + .. code-block:: console + + $ sudo pppd -detach noauth crtscts novj nodeflate nobsdcomp debug +ipv6 usepeerdns noipdefault defaultroute defaultroute6 ipv6cp-restart 5 ipcp-restart 5 + + Replace ```` by the device file assigned to the PPP UART and ```` by the baud rate of the UART that PPP is using (which is set in the :file:`overlay-ppp-without-cmux.overlay` file). + Typically, when ``uart1`` is assigned to be the PPP UART (in the devicetree overlay), the device file assigned to it is :file:`/dev/ttyACM2` for an nRF9160 DK, and :file:`/dev/ttyACM1` for the other nRF91 Series DKs. + +#. After the PPP link negotiation has completed successfully, a new network interface will be available, typically ``ppp0``. + This network interface will allow sending and receiving IP traffic through the modem of the nRF91 Series SiP running SLM. + +.. note:: + + You might encounter some issues with DNS resolution. + Edit the :file:`/etc/resolv.conf` file to work around these issues. + You can add DNS servers that are reachable with your current network configuration. + These added servers can even be the DNS servers that SLM's PPP sends as part of the PPP link negotiation, which are the DNS servers of the default PDN connection obtained from the modem. diff --git a/applications/serial_lte_modem/doc/SOCKET_AT_commands.rst b/applications/serial_lte_modem/doc/SOCKET_AT_commands.rst index e75283c90f1..0701be5df55 100644 --- a/applications/serial_lte_modem/doc/SOCKET_AT_commands.rst +++ b/applications/serial_lte_modem/doc/SOCKET_AT_commands.rst @@ -222,6 +222,7 @@ Syntax * The ```` parameter is an integer. It indicates to the modem the credential of the security tag to be used for establishing a secure connection. It is associated with a credential, that is, a certificate or PSK. The credential should be stored on the modem side beforehand. + Note that when ```` has a value of ``1``, ```` can only be used if ```` has a value of ``SOCK_STREAM`` and the :file:`overlay-native_tls.conf` configuration file is used. * The ```` parameter can accept one of the following values: @@ -539,32 +540,39 @@ Syntax * ```` is an integer that indicates the packet data network ID to bind to. - * ``50`` - :c:macro:`SO_RAI_NO_DATA` (set-only). - Immediately release the RRC. + * ``55`` - :c:macro:`SO_TCP_SRV_SESSTIMEO`. - * ```` is ignored. + * ```` is an integer that indicates the TCP server session inactivity timeout for a socket. + It accepts values from the range ``0`` to ``135``, where ``0`` is no timeout and ``135`` is 2 hours, 15 minutes. - * ``51`` - :c:macro:`SO_RAI_LAST` (set-only). - Enter Radio Resource Control (RRC) idle immediately after the next send operation. + * ``61`` - :c:macro:`SO_RAI` (set-only). + Release Assistance Indication (RAI). - * ```` is ignored. + * ```` The option accepts an integer, indicating the type of RAI. + Accepted values for the option are: - * ``52`` - :c:macro:`SO_RAI_ONE_RESP` (set-only). - Wait for one incoming packet after the next send operation, before entering RRC idle mode. + * ``1`` - :c:macro:`RAI_NO_DATA`. + Indicates that the application does not intend to send more data. + This socket option applies immediately and lets the modem exit connected mode more quickly. - * ```` is ignored. + * ``2`` - :c:macro:`RAI_LAST`. + Indicates that the application does not intend to send more data after the next call to :c:func:`send` or :c:func:`sendto`. + This lets the modem exit connected mode more quickly after sending the data. - * ``53`` - :c:macro:`SO_RAI_ONGOING` (set-only). - Keep RRC in connected mode after the next send operation (client). + * ``3`` - :c:macro:`RAI_ONE_RESP`. + Indicates that the application is expecting to receive just one data packet after the next call to :c:func:`send` or :c:func:`sendto`. + This lets the modem exit connected mode more quickly after having received the data. - * ```` is ignored. + * ``4`` - :c:macro:`RAI_ONGOING`. + Indicates that the application is expecting to receive just one data packet after the next call to :c:func:`send` or :c:func:`sendto`. + This lets the modem exit connected mode more quickly after having received the data. - * ``54`` - :c:macro:`SO_RAI_WAIT_MORE` (set-only). - Keep RRC in connected mode after the next send operation (server). + * ``5`` - :c:macro:`RAI_WAIT_MORE`. + Indicates that the socket is in active use by a server application. + This lets the modem stay in connected mode longer. - * ```` is ignored. -See `nRF socket options`_ for explanation of the supported options. +See :ref:`nRF socket options ` for explanation of the supported options. Examples ~~~~~~~~ @@ -639,7 +647,7 @@ Syntax * The ```` parameter can accept one of the following values: - * ``2`` - :c:macro:`TLS_HOSTNAME` (set-only). + * ``2`` - :c:macro:`TLS_HOSTNAME`. * ```` is a string that indicates the hostname to check against during TLS handshakes. It can be ``NULL`` to disable hostname verification. @@ -686,7 +694,7 @@ Syntax * ```` is an integer that indicates the DTLS handshake timeout in seconds. It can be one of the following values: ``1``, ``3``, ``7``, ``15``, ``31``, ``63``, ``123``. -See `nRF socket options`_ for explanation of the supported options. +See :ref:`nRF socket options ` for explanation of the supported options. Example diff --git a/applications/serial_lte_modem/doc/TCPUDP_AT_commands.rst b/applications/serial_lte_modem/doc/TCPUDP_AT_commands.rst index fbf5a8ff27e..c4505927dfd 100644 --- a/applications/serial_lte_modem/doc/TCPUDP_AT_commands.rst +++ b/applications/serial_lte_modem/doc/TCPUDP_AT_commands.rst @@ -69,7 +69,7 @@ This is emitted when a new connection has been created to the server. * The ```` value is the IPv4 or IPv6 address of the peer. -.. tcpsvr_disconnect_notif_start +.. slm_tcpsvr_disconnect_notif_start :: @@ -80,7 +80,7 @@ This is emitted when the client has been disconnected. * The ```` value is an integer. It is either ``0`` when the client is disconnected normally, or an *-errno* code. -.. tcpsvr_disconnect_notif_end +.. slm_tcpsvr_disconnect_notif_end Example @@ -205,7 +205,7 @@ Syntax * ``0`` - Do not verify the hostname against the received certificate. * ``1`` - Verify the hostname against the received certificate (default). -See `nRF socket options`_ ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. +See :ref:`nRF socket options ` ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. Response syntax ~~~~~~~~~~~~~~~ @@ -363,8 +363,8 @@ Response syntax ~~~~~~~~~~~~~~~ .. include:: TCPUDP_AT_commands.rst - :start-after: tcpsvr_disconnect_notif_start - :end-before: tcpsvr_disconnect_notif_end + :start-after: slm_tcpsvr_disconnect_notif_start + :end-before: slm_tcpsvr_disconnect_notif_end Examples ~~~~~~~~ @@ -583,7 +583,7 @@ Syntax * ``0`` - Do not verify the hostname against the received certificate. * ``1`` - Verify the hostname against the received certificate (default). -See `nRF socket options`_ ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. +See :ref:`nRF socket options ` ``peer_verify`` and ``tls_hostname`` for more information on ```` and ````. Response syntax ~~~~~~~~~~~~~~~ diff --git a/applications/serial_lte_modem/doc/images/teraterm.svg b/applications/serial_lte_modem/doc/images/teraterm.svg deleted file mode 100644 index 0a0a36130c5..00000000000 --- a/applications/serial_lte_modem/doc/images/teraterm.svg +++ /dev/null @@ -1,115 +0,0 @@ - - - - diff --git a/applications/serial_lte_modem/doc/images/termite.svg b/applications/serial_lte_modem/doc/images/termite.svg deleted file mode 100644 index b7e36fc7f26..00000000000 --- a/applications/serial_lte_modem/doc/images/termite.svg +++ /dev/null @@ -1,126 +0,0 @@ - - - - diff --git a/applications/serial_lte_modem/doc/nRF91_as_Zephyr_modem.rst b/applications/serial_lte_modem/doc/nRF91_as_Zephyr_modem.rst new file mode 100644 index 00000000000..250a73cde84 --- /dev/null +++ b/applications/serial_lte_modem/doc/nRF91_as_Zephyr_modem.rst @@ -0,0 +1,140 @@ +.. _slm_as_zephyr_modem: + +nRF91 Series as a Zephyr-compatible modem +######################################### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +Starting with |NCS| v2.6.0, the Serial LTE Modem (SLM) application can be used to turn an nRF91 Series SiP into a standalone modem that can be used through Zephyr's cellular modem driver. +This means that the controlling chip can run a Zephyr application that seamlessly uses Zephyr's IP stack instead of offloaded sockets via AT commands. + +This is made possible by SLM's support of CMUX and PPP and Zephyr's cellular modem driver. + +The :ref:`nRF52840 SoC present in the nRF9160 DK ` can even be made to be the controlling chip with the appropriate configuration (described below). +This is only possible on the nRF9160 DK, not on the other nRF91 Series DKs. + +.. note:: + + As of |NCS| |release|, Zephyr's GNSS driver does not support the nRF91 Series running SLM. + This functionality is part of planned future work. + +Configuration +************* + +Both SLM and the Zephyr application running on the controlling chip must be compiled with the appropriate configuration to make them work together. + +For that, Kconfig fragments and devicetree overlays must be added to the compilation command. + +See the :ref:`slm_config_files` section for information on how to compile with additional configuration files and a description of some of the mentioned Kconfig fragments. + +.. include:: CMUX_AT_commands.rst + :start-after: slm_cmux_baud_rate_note_start + :end-before: slm_cmux_baud_rate_note_end + +nRF91 Series SiP running SLM +============================ + +The following configuration files must be included: + +* :file:`overlay-cmux.conf` - To enable CMUX. +* :file:`overlay-ppp.conf` - To enable PPP. +* :file:`overlay-zephyr-modem.conf` - To tailor SLM to how Zephyr's cellular modem driver works. + This enables the :ref:`CONFIG_SLM_START_SLEEP ` Kconfig option, which makes the nRF91 Series SiP start only when the :ref:`power pin ` is toggled. + +In addition, if the controlling chip is an external MCU, the following files must also be included: + +* :file:`overlay-zephyr-modem-external-mcu.conf`- To define the power pin. + Make sure to update the defined pin so that it matches your setup. +* :file:`overlay-external-mcu.overlay` - To configure which UART SLM will use. + The actual configuration of the UART is defined in the :file:`*_ns.overlay` overlay file matching your board in the :file:`boards` directory. + Make sure to update the UART configuration (pins, baud rate) so that it matches your setup. + You can do this by modifying the properties of the node of the UART to be used, by editing either :file:`overlay-external-mcu.overlay` or the overlay file matching your board in the :file:`boards` directory. + +Or, if the controlling chip is the nRF52840 of the nRF9160 DK, the following files must also be included: + +* :file:`overlay-zephyr-modem-nrf9160dk-nrf52840.conf` - To define the power pin. +* :file:`overlay-zephyr-modem-nrf9160dk-nrf52840.overlay` - To configure the UART to be routed between the nRF9160 and the nRF52840 of the DK. + +Finally, if you want more verbose logging that includes the AT commands and responses, you can enable debug logging by uncommenting ``CONFIG_SLM_LOG_LEVEL_DBG=y`` in the :file:`prj.conf` configuration file. + +Controlling chip running Zephyr +=============================== + +Configuration files found in Zephyr's :zephyr:code-sample:`cellular-modem` sample are a good starting point. + +Specifically, regardless of what the controlling chip is, the Kconfig options found in the following files are needed: + +* :file:`prj.conf` - This file enables various Zephyr APIs, most of which are needed for proper functioning of the application. +* :file:`boards/nrf9160dk_nrf52840.conf` - This file tailors the configuration of the modem subsystem and driver to the SLM. + It makes the application's logs be output on UART 0 and also enables the debug logs of the cellular modem driver. + If you do not want the debug logs output by the driver, you may turn them off by removing ``CONFIG_MODEM_LOG_LEVEL_DBG=y``. + +In addition, depending on what the controlling chip is, the following devicetree overlay files are also needed. +They define the modem along with the UART it is connected to and its power pin. + +If the controlling chip is an external MCU: + +* :file:`boards/nrf9160dk_nrf9160_ns.overlay` - The UART configuration and power pin can be customized according to your setup. + +If the controlling chip is the nRF52840 of the nRF9160 DK: + +* :file:`boards/nrf9160dk_nrf52840.overlay` - The UART and power pin are configured to be routed to the nRF9160. + +Developing the Zephyr application +********************************* + +To get started developing the Zephyr application running on the controlling chip, look at the code of Zephyr's :zephyr:code-sample:`cellular-modem` sample to see how the modem is managed and used. +You can even compile, flash and run the sample to verify proper operation of the modem. + +Flashing and running +******************** + +When built with the Zephyr-compatible modem configuration, SLM will put the nRF91 Series SiP to deep sleep when powered on. +Zephyr's cellular modem driver running on the controlling chip will take care of waking up the nRF91 Series SiP, so it is advised to first flash SLM to the nRF91 Series SiP. + +However, before flashing the SLM built with the Zephyr-compatible modem configuration, make sure that the nRF91 Series modem has been set to the desired system mode. +For this, you will need a regular SLM running in the nRF91 Series SiP to be able to run AT commands manually. +To set the modem to the desired system mode, issue an ``AT%XSYSTEMMODE`` command followed by an ``AT+CFUN=0`` command so that the modem saves the system mode to NVM. +For example, to enable only LTE-M, issue the following command: ``AT%XSYSTEMMODE=0,1,0,0`` +You need to do this because the modem's system mode is not automatically set at any point, so the one already configured will be used. + +Additionally, if the controlling chip is an external MCU: + +* Make sure that the UART and the power pin are wired according to how they are configured in both the external MCU and the nRF91 Series SiP. + +Or if the controlling chip is the nRF52840 of the nRF9160 DK: + +* Make sure that the **PROG/DEBUG SW10** switch on the DK is set to **NRF91** when flashing SLM, and to **NRF52** when flashing the Zephyr application. + The switch also affects which chip is reset when the Reset button is pressed. +* No wiring is needed as the routing between the pins happens internally. + +To observe the operation sequence, you can view the application logs coming from both chips. + +By default, SLM will output its logs through RTT, and the Zephyr application running on the controlling chip through its UART 0. +The RTT logs can be seen with an RTT client such as ``JLinkRTTViewer``. +If SLM is running on the nRF9160 DK, the **PROG/DEBUG SW10** switch needs to be set to **NRF91** to be able to receive the RTT logs. +However, for convenience you may want to redirect SLM's logs to the SiP's UART 0 so that you do not need to reconnect the RTT client every time the board is reset. +See the :ref:`slm_additional_config` section for information on how to do this. + +The logs output via UART can be seen by connecting to the appropriate UART with a serial communication program. +Under Linux, if the controlling chip is the nRF52840 of the nRF9160 DK, the device file of its UART 0 will typically be :file:`/dev/ttyACM1`. + +After both applications have been flashed to their respective chips and you are connected to receive logs, you can reset the controlling chip. +When the Zephyr application starts up, the following happens: + +* If power management is enabled (the :kconfig:option:`CONFIG_PM_DEVICE` Kconfig option is set to ``y``): when the application powers on the modem (by calling ``pm_device_action_run(, PM_DEVICE_ACTION_RESUME)`` as the sample does), the cellular modem driver will toggle the modem's power pin to wake it up. + + If power management is not enabled, the cellular modem driver will automatically proceed and expect SLM to already be started and in a pristine state. + In this case, SLM should be compiled with the :ref:`CONFIG_SLM_START_SLEEP ` Kconfig option set to ``n``, and :ref:`CONFIG_SLM_POWER_PIN ` can be left undefined. + +* The cellular modem driver will start sending AT commands to SLM. + It will enable the network status notifications, gather some information from the modem, enable CMUX, and set the modem to normal mode (with an ``AT+CFUN=1`` command). + This will result in SLM's PPP starting automatically when the network registration is complete. + +* From this point onwards, once the Zephyr application has brought up the driver's network interface, it will be able to send and receive IP traffic through it. + The :zephyr:code-sample:`cellular-modem` sample does this. diff --git a/applications/serial_lte_modem/doc/slm_data_mode.rst b/applications/serial_lte_modem/doc/slm_data_mode.rst index ba20d22c06e..a0503ef38a5 100644 --- a/applications/serial_lte_modem/doc/slm_data_mode.rst +++ b/applications/serial_lte_modem/doc/slm_data_mode.rst @@ -51,7 +51,7 @@ Other examples: * ``AT#XFTP="mput",`` * ``AT#XMQTTPUB=,"",,`` * ``AT#XNRFCLOUD=2`` -* ``AT#XCARRIER="app_data"`` +* ``AT#XCARRIER="app_data_set"`` The SLM application sends an *OK* response when it successfully enters data mode. diff --git a/applications/serial_lte_modem/doc/slm_description.rst b/applications/serial_lte_modem/doc/slm_description.rst index 8e1b658a621..3400a46e687 100644 --- a/applications/serial_lte_modem/doc/slm_description.rst +++ b/applications/serial_lte_modem/doc/slm_description.rst @@ -20,7 +20,7 @@ The application accepts both the modem-specific AT commands and proprietary AT c The AT commands are documented in the following guides: * Modem-specific AT commands - `nRF91x1 AT Commands Reference Guide`_ and `nRF9160 AT Commands Reference Guide`_ -* Proprietary AT commands - :ref:`SLM_AT_intro` +* Proprietary AT commands - :ref:`SLM_AT_commands` Requirements ************ @@ -36,13 +36,11 @@ Configuration |config| -.. _slm_config: +.. _slm_config_options: Configuration options ===================== -Check and configure the following configuration options for the sample: - .. _CONFIG_SLM_CUSTOMER_VERSION: CONFIG_SLM_CUSTOMER_VERSION - Customer version string @@ -54,30 +52,59 @@ CONFIG_SLM_CUSTOMER_VERSION - Customer version string CONFIG_SLM_AT_MAX_PARAM - AT command parameter count limit This defines the maximum number of parameters allowed in an AT command, including the command name. +.. _CONFIG_SLM_CMUX: + +CONFIG_SLM_CMUX - Enable CMUX functionality + This option is enabled by the CMUX overlay. + It adds support for CMUX. + See :ref:`SLM_AT_CMUX` for more information. + +.. _CONFIG_SLM_PPP: + +CONFIG_SLM_PPP - Enable PPP functionality + This option is enabled by the PPP overlay. + It adds support for PPP. + PPP can be used in conjunction with :ref:`CMUX ` in order to use a single UART for both AT data and PPP. + When CMUX is also enabled, PPP is usable only through a CMUX channel. + See :ref:`SLM_AT_PPP` for more information. + .. _CONFIG_SLM_NATIVE_TLS: -CONFIG_SLM_NATIVE_TLS - Use Zephyr mbedTLS - This option enables using Zephyr's mbedTLS. - It requires additional configuration. +CONFIG_SLM_NATIVE_TLS - Use Zephyr's Mbed TLS for TLS connections + This option is enabled by the native TLS overlay. See :ref:`slm_native_tls` for more information. +.. _CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE: + +CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE - Buffer space reserved for loading credentials + Specifies the credential buffer size available for a single ``sec_tag`` when loading credentials for Mbed TLS. + The default value is ``4096``. + +.. _CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_COUNT: + +CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_COUNT - Number of buffers for loading credentials + The number of buffers available for loading ``sec_tag`` credentials for Mbed TLS. + TLS client only needs the buffer when connecting, while TLS server needs the buffer as long as it is running. + Increase the value if you need both TLS client and server running simultaneously with different ``sec_tags``. + The default value is ``1``. + .. _CONFIG_SLM_EXTERNAL_XTAL: CONFIG_SLM_EXTERNAL_XTAL - Use external XTAL for UARTE This option configures the application to use an external XTAL for UARTE. For the nRF9160 DK, see the `nRF9160 Product Specification`_ (section 6.19 UARTE) for more information. - For the nRF9161 DK, see the `nRF9161 Objective Product Specification`_ (section 6.19 UARTE) for more information. + For the nRF9161 DK, see the `nRF9161 Product Specification`_ (section 6.19 UARTE) for more information. .. _CONFIG_SLM_START_SLEEP: CONFIG_SLM_START_SLEEP - Enter sleep on startup This option makes an nRF91 Series device enter deep sleep after startup. - It is not selected by default. + It is not enabled by default. -.. _CONFIG_SLM_WAKEUP_PIN: +.. _CONFIG_SLM_POWER_PIN: -CONFIG_SLM_WAKEUP_PIN - Interface GPIO to exit from sleep or idle - This option specifies which interface GPIO to use for exiting sleep or idle mode. +CONFIG_SLM_POWER_PIN - Interface GPIO pin to power off the SiP and exit from sleep or idle + This option specifies which pin to use to power on or off the SiP and make SLM exit idle mode. It is set by default as follows: * On the nRF9161 DK: @@ -93,13 +120,13 @@ CONFIG_SLM_WAKEUP_PIN - Interface GPIO to exit from sleep or idle * On Thingy:91, **P0.26** (Multi-function button on Thingy:91) is used. .. note:: - This pin is used as input GPIO and configured as *Active Low*. - By default, the application pulls up this GPIO. + This pin is configured with a pull up, so it is active low. + It must be pulled down for a short time to perform one power off or wake up operation. .. _CONFIG_SLM_INDICATE_PIN: -CONFIG_SLM_INDICATE_PIN - Interface GPIO to indicate data available or unsolicited event notifications - This option specifies which interface GPIO to use for indicating data available or unsolicited event notifications from the modem. +CONFIG_SLM_INDICATE_PIN - Interface GPIO pin to indicate data available or unsolicited event notifications + This option specifies which pin to use for indicating data available or unsolicited event notifications from the modem. It is set by default as follows: * On the nRF9161 DK: @@ -115,8 +142,7 @@ CONFIG_SLM_INDICATE_PIN - Interface GPIO to indicate data available or unsolicit * It is not defined when the target is Thingy:91. .. note:: - This pin is used as output GPIO and configured as *Active Low*. - By default, the application sets this GPIO as *Inactive High*. + This pin is configured to be active low, so it will be high when inactive. .. _CONFIG_SLM_INDICATE_TIME: @@ -220,7 +246,7 @@ CONFIG_SLM_TWI - TWI support in SLM .. _CONFIG_SLM_UART_RX_BUF_COUNT: CONFIG_SLM_UART_RX_BUF_COUNT - Receive buffers for UART. - This option defines the amount of buffers for receiving (RX) UART traffic. + This option defines the number of buffers for receiving (RX) UART traffic. The default value is 3. .. _CONFIG_SLM_UART_RX_BUF_SIZE: @@ -235,6 +261,8 @@ CONFIG_SLM_UART_TX_BUF_SIZE - Send buffer size for UART. This option defines the size of the buffer for sending (TX) UART traffic. The default value is 256. +.. _slm_additional_config: + Additional configuration ======================== @@ -251,16 +279,27 @@ To switch to UART output, change the following options in the :file:`prj.conf` f CONFIG_LOG_BACKEND_RTT=n CONFIG_LOG_BACKEND_UART=y +.. _slm_config_files: Configuration files =================== -The sample provides predefined configuration files for both the parent image and the child image. You can find the configuration files in the :file:`applications/serial_lte_modem` directory. +In general, they have an ``overlay-`` prefix, and a :file:`.conf` or :file:`.overlay` extension for Kconfig or devicetree overlays, respectively. +Board-specific configuration files are named :file:`` with a :file:`.conf` or :file:`.overlay` extension and are located in the :file:`boards` directory. +When the name of the board-specific configuration file matches the build target, the overlay is automatically included by the build system. + +See :ref:`app_build_system`: for more information on the |NCS| configuration system. + +.. important:: + + When adding Kconfig fragments and devicetree overlays, make sure to use the ``-DEXTRA_CONF_FILE`` and ``-DEXTRA_DTC_OVERLAY_FILE`` CMake parameters, respectively. + Otherwise, if ``-DCONF_FILE`` or ``-DDTC_OVERLAY_FILE`` is used, all the configuration files that normally get picked up automatically will have to be included explicitly. + The following configuration files are provided: -* :file:`prj.conf` - This configuration file contains the standard configuration for the serial LTE modem application. +* :file:`prj.conf` - This configuration file contains the standard configuration for the serial LTE modem application and is included by default by the build system. * :file:`overlay-native_tls.conf` - This configuration file contains additional configuration options that are required to use :ref:`slm_native_tls`. You can include it by adding ``-DEXTRA_CONF_FILE=overlay-native_tls.conf`` to your build command. @@ -272,6 +311,24 @@ The following configuration files are provided: * :file:`overlay-full_fota.conf` - Configuration file that adds full modem FOTA support. See :ref:`SLM_AT_FOTA` for more information on how to use full modem FOTA functionality. +* :file:`overlay-cmux.conf` - Configuration file that adds support for the CMUX protocol. + See :ref:`SLM_AT_CMUX` for more information. + +* :file:`overlay-ppp.conf` - Configuration file that adds support for the Point-to-Point Protocol (PPP). + This disables most of the IP-based protocols available through AT commands (such as FTP and MQTT) as it is expected that the controlling chip's own IP stack is used instead. + See :ref:`CONFIG_SLM_PPP ` and :ref:`SLM_AT_PPP` for more information. + +* :file:`overlay-ppp-without-cmux.conf` - Kconfig fragment that configures the UART to be used by PPP. + This configuration file should be included when building SLM with PPP and without CMUX. + +* :file:`overlay-ppp-without-cmux.overlay` - Devicetree overlay that configures the UART to be used by PPP. + This configuration file should be included when building SLM with PPP and without CMUX, in addition to :file:`overlay-ppp.conf`. + It can be customized to fit your configuration (UART, baud rate, and so on). + By default, it sets the baud rate of the PPP UART to 1 000 000. + +* :file:`overlay-zephyr-modem.conf`, :file:`overlay-zephyr-modem-external-mcu.conf`, :file:`overlay-zephyr-modem-nrf9160dk-nrf52840.conf`, :file:`overlay-external-mcu.overlay`, and :file:`overlay-zephyr-modem-nrf9160dk-nrf52840.overlay` - These configuration files are used when compiling SLM to turn an nRF91 Series SiP into a Zephyr-compatible standalone modem. + See :ref:`slm_as_zephyr_modem` for more information. + * :file:`boards/nrf9160dk_nrf9160_ns.conf` - Configuration file specific for the nRF9160 DK. This file is automatically merged with the :file:`prj.conf` file when you build for the ``nrf9160dk_nrf9160_ns`` build target. @@ -281,42 +338,29 @@ The following configuration files are provided: * :file:`boards/thingy91_nrf9160_ns.conf` - Configuration file specific for Thingy:91. This file is automatically merged with the :file:`prj.conf` file when you build for the ``thingy91_nrf9160_ns`` build target. -In general, Kconfig overlays have an ``overlay-`` prefix and a :file:`.conf` extension. -Board-specific configuration files are named :file:`.conf` and are located in the :file:`boards` folder. -DTS overlay files are named as the build target they are meant to be used with, and use the file extension :file:`.overlay`. -They are also placed in the :file:`boards` folder. -When the DTS overlay filename matches the build target, the overlay is automatically chosen and applied by the build system. - -See :ref:`app_build_system`: for more information on the |NCS| configuration system. - .. _slm_native_tls: Native TLS ---------- -By default, the secure socket (TLS/DTLS) is offloaded onto the modem. -However, if you need customized TLS/DTLS features that are not supported by the modem firmware, you can use native TLS instead. +By default, the secure socket (TLS) is offloaded to the modem. +If you need customized TLS features that are not supported by the modem firmware, you can use native TLS instead. +Native TLS uses the Mbed TLS library in Zephyr to establish secure connectivity. Currently, the SLM application can be built to use native TLS for the following services: * Secure socket +* TLS Proxy client * TLS Proxy server * HTTPS client -If native TLS is enabled, you must use the ``AT#XCMNG`` command to store the credentials. +With native TLS, the credentials are stored in the Zephyr settings storage with the ``AT#XCMNG`` command. -.. note:: - - The modem needs to be in an offline state when storing the credentials. - The SLM application supports security tags ranging from ``0`` to ``214748364``. - -The configuration options that are required to enable the native TLS socket are defined in the :file:`overlay-native_tls.conf` file. +The configuration options that are required to enable native TLS are defined in the :file:`overlay-native_tls.conf` file. .. note:: - Native TLS sockets have the following limitations: + Native TLS services have the following limitations: - * PSK, PSK identity, and PSK public key are currently not supported. - * The DTLS server is currently not supported. * TLS session resumption is currently not supported. .. include:: /libraries/modem/nrf_modem_lib/nrf_modem_lib_trace.rst @@ -358,30 +402,15 @@ To connect to an nRF91 Series DK with a PC: Using the Cellular Monitor app in combination with the nRF Connect Serial Terminal shows how the modem responds to the different modem commands. You can then use this connection to send or receive AT commands over UART, and to see the log output of the development kit. - Alternatively, you can use a terminal emulator like `Termite`_, `Teraterm`_, or PuTTY to establish a terminal connection to the development kit, using the following settings: - - * Baud rate: 115200 - * 8 data bits - * 1 stop bit - * No parity - * HW flow control: None + Instead of using nRF Connect Serial Terminal, you can use PuTTY to establish a terminal connection to the development kit, using the :ref:`default serial port connection settings `. .. note:: The default AT command terminator is a carriage return followed by a line feed (``\r\n``). nRF Connect Serial Terminal supports this format. If you want to use another terminal emulator, make sure that the configured AT command terminator corresponds to the line terminator of your terminal. - - When using `Termite`_ and `Teraterm`_, configure the AT command terminator as follows: - - .. figure:: images/termite.svg - :alt: Termite configuration for sending AT commands through UART - - .. figure:: images/teraterm.svg - :alt: Teraterm configuration for sending AT commands through UART - - When using PuTTY, you must set the :ref:`CONFIG_SLM_CR_TERMINATION ` SLM configuration option instead. - See :ref:`application configuration ` for more details. + When using PuTTY, you must set the :ref:`CONFIG_SLM_CR_TERMINATION ` SLM configuration option. + See :ref:`slm_config_options` for more details. .. slm_connecting_91dk_pc_instr_end @@ -409,14 +438,14 @@ To connect with an external MCU using UART_2, change the configuration files for # unmask the following config #CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 #CONFIG_UART_0_NRF_HW_ASYNC=y - #CONFIG_SLM_WAKEUP_PIN=8 + #CONFIG_SLM_POWER_PIN=8 #CONFIG_SLM_INDICATE_PIN=0 # Use UART_2 (when working with external MCU) # unmask the following config CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 CONFIG_UART_2_NRF_HW_ASYNC=y - CONFIG_SLM_WAKEUP_PIN=31 + CONFIG_SLM_POWER_PIN=31 CONFIG_SLM_INDICATE_PIN=30 * In the :file:`nrf9161dk_nrf9161_ns.overlay` file:: @@ -451,14 +480,14 @@ To connect with an external MCU using UART_2, change the configuration files for # unmask the following config #CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 #CONFIG_UART_0_NRF_HW_ASYNC=y - #CONFIG_SLM_WAKEUP_PIN=6 + #CONFIG_SLM_POWER_PIN=6 #CONFIG_SLM_INDICATE_PIN=2 # Use UART_2 (when working with external MCU) # unmask the following config CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 CONFIG_UART_2_NRF_HW_ASYNC=y - CONFIG_SLM_WAKEUP_PIN=31 + CONFIG_SLM_POWER_PIN=31 CONFIG_SLM_INDICATE_PIN=30 @@ -529,18 +558,19 @@ Communicating with the modem on Thingy:91 ========================================= In this scenario, Thingy:91 running the Serial LTE Modem application serves as the host. -You can use only a PC as a client. +You can use a PC as a client. .. _slm_connecting_thingy91_pc: Connecting with a PC -------------------- -To connect to Thingy:91 with a PC, you must first program the :ref:`connectivity_bridge` on the nrf52840 of Thingy:91. -It routes ``UART_0`` to ``USB_CDC0`` on Thingy:91. -By enabling the option ``CONFIG_BRIDGE_BLE_ENABLE`` , you can also use SLM over :ref:`nus_service_readme`. +The nRF52840 SoC of Thingy:91 is pre-programmed with the :ref:`connectivity_bridge` application. +To update the :ref:`connectivity_bridge` application, see the :ref:`programming_thingy` documentation. +The :ref:`connectivity_bridge` application routes ``UART_0`` to ``USB_CDC0`` on Thingy:91. +By enabling the :kconfig:option:`CONFIG_BRIDGE_BLE_ENABLE` Kconfig option in the :ref:`connectivity_bridge`, you can also use SLM over :ref:`nus_service_readme`. -Then follow the instructions below: +To connect to a Thingy:91 with a PC: .. include:: slm_description.rst :start-after: .. slm_connecting_91dk_pc_instr_start diff --git a/applications/serial_lte_modem/doc/slm_extending.rst b/applications/serial_lte_modem/doc/slm_extending.rst index eef9431bc66..5fb09243c27 100644 --- a/applications/serial_lte_modem/doc/slm_extending.rst +++ b/applications/serial_lte_modem/doc/slm_extending.rst @@ -7,46 +7,37 @@ Extending the application :local: :depth: 2 -You can extend the serial LTE modem application by adding your own AT commands and custom error handling. +The AT commands in the Serial LTE modem are implemented with the :ref:`at_cmd_custom_readme` library. +You can extend the Serial LTE modem application by adding your own AT commands. Adding AT commands ****************** -If you want to implement custom AT commands and add them to the serial LTE modem application, see the parser implementation of the provided proprietary AT commands for reference. -The source files can be found in the :file:`applications/serial_lte_modem/src/` folder. +If you want to implement a custom AT command in SLM, you will need to follow the instructions in the :ref:`at_cmd_custom_readme` library documentation. +Setting the AT command filter and callback with the :c:macro:`AT_CMD_CUSTOM` macro is enough for a custom AT command that does not require setup or teardown. -Complete the following steps to add a parser for your own AT commands: +As a preferred alternative to the :c:macro:`AT_CMD_CUSTOM` macro, SLM defines the :c:macro:`SLM_AT_CMD_CUSTOM` macro, which is a wrapper around the :c:macro:`AT_CMD_CUSTOM` macro. +The :c:macro:`SLM_AT_CMD_CUSTOM` macro pre-processes the AT command parameters for the AT command callback and sets the default ``OK`` response if the callback returns successfully. -1. Create a header file in :file:`applications/serial_lte_modem/src/`. - The file must expose the following functions: - - * ``*_init()`` - Initialize the parser. - * ``*_uninit()`` - Uninitialize the parser. - - See the files for existing AT command parsers for reference. -#. Implement your AT strings and handlers in a corresponding :file:`.c` file. - See the files for existing AT command parsers for reference. +If your custom AT command requires setup or teardown, you will need to perform the following steps: - Pay attention to the following requirements: - - * The names of new AT commands should start with ``AT#X``. - * Before entering idle state, the serial LTE modem application will call the uninit function. - Make sure that the uninit function exits successfully. - Otherwise, the application cannot enter idle state. -#. Edit :file:`applications/serial_lte_modem/src/slm_at_commands.c` and add calls to your functions: +1. Create a header file in :file:`applications/serial_lte_modem/src/`. + The file must expose the following function declarations: - a. In ``slm_at_init()``, add a call to your init function. - #. In ``slm_at_uninit()``, add a call to your uninit function. - #. Declare your command handler like those of other service modules. - #. In ``slm_at_cmd_list``, add the mapping of your AT command and its handler. + * ``*_init()`` - Your setup function for the custom AT command. + * ``*_uninit()`` - Your teardown function for the custom AT command. -If you discover any bugs in the :file:`main.c`, :file:`slm_at_host.h`, or :file:`slm_at_host.c` files, report them on the `DevZone`_. +#. Create a corresponding :file:`.c` file in :file:`applications/serial_lte_modem/src/`. + The file must implement the following functions: -Error handling -************** + * Your AT command callback, which is declared with the :c:macro:`AT_CMD_CUSTOM` macro. + * ``*_init()`` - Your setup function for the custom AT command. + * ``*_uninit()`` - Your teardown function for the custom AT command. + Make sure that the teardown function exits successfully. + It will be called before entering power saving states or shutting down. -The Serial LTE modem application returns error codes that are defined in :file:`zephyr/lib/libc/minimal/include/errno.h`. -See the comments in that file for information about a specific error. +#. Edit :file:`applications/serial_lte_modem/src/slm_at_commands.c` and make the following changes: -If an error occurs during TCP/IP processing, the socket is usually closed. -See the `POSIX Programmer's Manual`_ for information about the errors returned by each API. + a. Include your header file. + #. In the ``slm_at_init()`` function, add a call to your setup function. + #. In the ``slm_at_uninit()`` function, add a call to your teardown function. diff --git a/applications/serial_lte_modem/doc/slm_testing.rst b/applications/serial_lte_modem/doc/slm_testing.rst index ea7b1fef8d7..ef91220d37b 100644 --- a/applications/serial_lte_modem/doc/slm_testing.rst +++ b/applications/serial_lte_modem/doc/slm_testing.rst @@ -477,7 +477,7 @@ DTLS client The DTLS client requires connection-based UDP to trigger the DTLS establishment. -Before completing this test, you must update the Pre-shared Key (PSK) and the PSK identity to be used for the TLS connection in the modem. +Before completing this test, you must update the pre-shared key (PSK) and the PSK identity to be used for the TLS connection in the modem. The credentials must use the security tag 16842756. To store the credentials in the modem, enter the following AT commands: diff --git a/applications/serial_lte_modem/overlay-carrier.conf b/applications/serial_lte_modem/overlay-carrier.conf index 5a38ff0c1d5..c0f1e53d429 100644 --- a/applications/serial_lte_modem/overlay-carrier.conf +++ b/applications/serial_lte_modem/overlay-carrier.conf @@ -25,3 +25,6 @@ CONFIG_SLM_CUSTOMER_VERSION="lwm2m_carrier" # Enable LwM2M carrier settings support CONFIG_LWM2M_CARRIER_SETTINGS=y + +# DFU target library +CONFIG_DFU_TARGET=y diff --git a/applications/serial_lte_modem/overlay-cmux.conf b/applications/serial_lte_modem/overlay-cmux.conf new file mode 100644 index 00000000000..900d9876b68 --- /dev/null +++ b/applications/serial_lte_modem/overlay-cmux.conf @@ -0,0 +1,17 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_SLM_CMUX=y + +# Zephyr modem subsystem +CONFIG_MODEM_MODULES=y +CONFIG_MODEM_CMUX=y +CONFIG_MODEM_BACKEND_UART=y +CONFIG_MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS=1000 + +# debug options +#CONFIG_MODEM_CMUX_LOG_LEVEL_DBG=y +#CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y diff --git a/applications/serial_lte_modem/overlay-external-mcu.overlay b/applications/serial_lte_modem/overlay-external-mcu.overlay new file mode 100644 index 00000000000..ec42d212922 --- /dev/null +++ b/applications/serial_lte_modem/overlay-external-mcu.overlay @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + ncs,slm-uart = &uart2; + }; +}; + +&uart2 { + status = "okay"; +}; + +/* uart0 is not needed if no logging is received there. */ +&uart0 { + status = "disabled"; +}; diff --git a/applications/serial_lte_modem/overlay-full_fota.conf b/applications/serial_lte_modem/overlay-full_fota.conf index 3f7fec68775..4888eb850a5 100644 --- a/applications/serial_lte_modem/overlay-full_fota.conf +++ b/applications/serial_lte_modem/overlay-full_fota.conf @@ -4,6 +4,9 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # +# This overlay requires a board with an external flash. +# For nRF9160 DKs, only revisions 0.14.0 and later have one. + # Enable external flash for full FOTA CONFIG_SPI_NOR=y diff --git a/applications/serial_lte_modem/overlay-native_tls.conf b/applications/serial_lte_modem/overlay-native_tls.conf index ca19b9d3a2b..c8245dd9edd 100644 --- a/applications/serial_lte_modem/overlay-native_tls.conf +++ b/applications/serial_lte_modem/overlay-native_tls.conf @@ -5,6 +5,8 @@ # CONFIG_SLM_NATIVE_TLS=y +# Enable offloading with TLS_NATIVE. +CONFIG_NET_SOCKETS_OFFLOAD_DISPATCHER=y # Enable legacy crypto support CONFIG_NRF_SECURITY=y CONFIG_NORDIC_SECURITY_BACKEND=y @@ -14,8 +16,8 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_TLS_LIBRARY=y CONFIG_MBEDTLS_SSL_SRV_C=y CONFIG_MBEDTLS_CIPHER=y -# Enable loading the modem with TLS certificates and keys. -CONFIG_MODEM_KEY_MGMT=y +# Reserve enough settings space for the certificates +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x4000 # Set maximum TLS contexts. # Increase also CONFIG_POSIX_MAX_FDS, if you need more TLS contexts. CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2 @@ -26,6 +28,7 @@ CONFIG_POSIX_MAX_FDS=10 CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=4096 CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 CONFIG_MBEDTLS_ENABLE_HEAP=y +# Raise to 64000 for two simultaneous TLS connections CONFIG_MBEDTLS_HEAP_SIZE=36864 # Enable TLS protocol options CONFIG_NET_SOCKETS_SOCKOPT_TLS=y @@ -35,6 +38,8 @@ CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y CONFIG_MBEDTLS_AES_C=y CONFIG_MBEDTLS_CCM_C=y CONFIG_MBEDTLS_GCM_C=y +CONFIG_MBEDTLS_CIPHER_MODE_CBC=y +CONFIG_MBEDTLS_CIPHER_PADDING_PKCS7=y # Enable ECC CONFIG_MBEDTLS_ECP_C=y CONFIG_PSA_WANT_ECC_SECP_R1_256=y @@ -43,6 +48,8 @@ CONFIG_MBEDTLS_ECDSA_C=y CONFIG_PSA_WANT_ALG_ECDSA=y CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y CONFIG_PSA_WANT_ALG_DETERMINISTIC_ECDSA=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR=y # dep for DETERMINISTIC_ECDSA +CONFIG_PSA_WANT_ALG_HMAC=y # dep for DETERMINISTIC_ECDSA # Enable ECDH CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED=y CONFIG_MBEDTLS_ECDH_C=y @@ -51,13 +58,18 @@ CONFIG_PSA_WANT_ALG_ECDH=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED=y # Enable RSA -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y CONFIG_MBEDTLS_RSA_C=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y CONFIG_MBEDTLS_PKCS1_V15=y CONFIG_MBEDTLS_MPI_MAX_SIZE=512 +CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y +CONFIG_PSA_WANT_RSA_KEY_SIZE_2048=y +CONFIG_PSA_WANT_RSA_KEY_SIZE_4096=y # Enable SHA CONFIG_MBEDTLS_SHA256_C=y CONFIG_MBEDTLS_SHA512_C=y +# Enable PSK key exchange +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y # Disable MBEDTLS modules CONFIG_MBEDTLS_CTR_DRBG_C=n @@ -78,3 +90,8 @@ CONFIG_MBEDTLS_SHA1_C=n # Enable Socket Logging for debug #CONFIG_NET_LOG=y #CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y + +# Enable Mbed TLS logs +#CONFIG_MBEDTLS_DEBUG=y +#CONFIG_MBEDTLS_DEBUG_C=y +#CONFIG_MBEDTLS_DEBUG_LEVEL=3 diff --git a/applications/serial_lte_modem/overlay-ppp-without-cmux.conf b/applications/serial_lte_modem/overlay-ppp-without-cmux.conf new file mode 100644 index 00000000000..3a211c63aee --- /dev/null +++ b/applications/serial_lte_modem/overlay-ppp-without-cmux.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Include this Kconfig fragment only if using PPP without CMUX. + +# Ensure that HW RX byte counting is enabled for the PPP UART. This especially matters at higher baud rates. +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 + +# TF-M cannot have the UART for itself. +CONFIG_TFM_SECURE_UART_SHARE_INSTANCE=y diff --git a/applications/serial_lte_modem/overlay-ppp-without-cmux.overlay b/applications/serial_lte_modem/overlay-ppp-without-cmux.overlay new file mode 100644 index 00000000000..f256f2c6974 --- /dev/null +++ b/applications/serial_lte_modem/overlay-ppp-without-cmux.overlay @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Include this devicetree overlay only if using PPP without CMUX. */ + + / { + chosen { + ncs,slm-ppp-uart = &uart1; + }; +}; + +/* PPP UART. Baud rates other than 115200/230400/1000000 didn't work on uart1. */ +&uart1 { + status = "okay"; + hw-flow-control; + current-speed = <1000000>; +}; diff --git a/applications/serial_lte_modem/overlay-ppp.conf b/applications/serial_lte_modem/overlay-ppp.conf index 43e944c7341..b1c5bc6925d 100644 --- a/applications/serial_lte_modem/overlay-ppp.conf +++ b/applications/serial_lte_modem/overlay-ppp.conf @@ -18,18 +18,13 @@ CONFIG_AT_CMD_CUSTOM=y CONFIG_NRF_MODEM_LIB_SHMEM_TX_SIZE=22528 -# PPP UART -CONFIG_UART_1_NRF_HW_ASYNC=y -CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 - -# TF-M cannot have its own UART. -CONFIG_TFM_SECURE_UART_SHARE_INSTANCE=y - # Zephyr PPP support CONFIG_NET_NATIVE=y CONFIG_NET_L2_PPP=y -CONFIG_NET_DRIVERS=y -CONFIG_NET_PPP=y +CONFIG_MODEM_MODULES=y +CONFIG_MODEM_PPP=y +CONFIG_MODEM_BACKEND_UART=y +CONFIG_MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS=1000 # L2 protocol CONFIG_NET_L2_PPP_MGMT=y @@ -39,16 +34,6 @@ CONFIG_NET_L2_PPP_OPTION_SERVE_DNS=y CONFIG_NET_L2_PPP_TIMEOUT=5000 CONFIG_NET_L2_PPP_MAX_CONFIGURE_REQ_RETRANSMITS=20 -# UART driver -CONFIG_NET_PPP_ASYNC_UART=y -CONFIG_NET_PPP_UART_BUF_LEN=2048 -CONFIG_NET_PPP_ASYNC_UART_TX_BUF_LEN=4096 -CONFIG_NET_PPP_RINGBUF_SIZE=4096 -CONFIG_NET_PPP_RX_STACK_SIZE=2048 -CONFIG_NET_PPP_VERIFY_FCS=n -CONFIG_PPP_CLIENT_CLIENTSERVER=y # Windows support -CONFIG_PPP_NET_IF_NO_AUTO_START=y - # IP stack CONFIG_NET_IPV4=y CONFIG_NET_IPV6=y @@ -65,11 +50,10 @@ CONFIG_NET_BUF_TX_COUNT=88 CONFIG_NET_TC_RX_COUNT=0 # debug options -#CONFIG_LOG_BUFFER_SIZE=16384 #CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=4096 -#CONFIG_LOG_DEFAULT_LEVEL=4 #CONFIG_NET_LOG=y #CONFIG_NET_PKT_LOG_LEVEL_DBG=y -#CONFIG_NET_PPP_LOG_LEVEL_DBG=y #CONFIG_NET_L2_PPP_LOG_LEVEL_DBG=y +#CONFIG_NET_MGMT_EVENT_LOG_LEVEL_DBG=y +#CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y #CONFIG_UART_LOG_LEVEL_DBG=y diff --git a/applications/serial_lte_modem/overlay-ppp.overlay b/applications/serial_lte_modem/overlay-ppp.overlay deleted file mode 100644 index 9391eddc0b1..00000000000 --- a/applications/serial_lte_modem/overlay-ppp.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - - / { - chosen { - zephyr,ppp-uart = &uart1; - }; -}; - -/* PPP UART. Baud rates other than 115200/230400/1000000 didn't work on uart1. */ -&uart1 { - status = "okay"; - hw-flow-control; - current-speed = <1000000>; -}; diff --git a/applications/serial_lte_modem/overlay-zephyr-modem-external-mcu.conf b/applications/serial_lte_modem/overlay-zephyr-modem-external-mcu.conf new file mode 100644 index 00000000000..10954a59986 --- /dev/null +++ b/applications/serial_lte_modem/overlay-zephyr-modem-external-mcu.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Ensure that HW RX byte counting is enabled. This especially matters at higher baud rates. +CONFIG_UART_2_NRF_HW_ASYNC=y +CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 + +# Update this value so that it is in accordance with your setup. +CONFIG_SLM_POWER_PIN=-1 diff --git a/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.conf b/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.conf new file mode 100644 index 00000000000..3a112c7c1b1 --- /dev/null +++ b/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Ensure that HW RX byte counting is enabled. This especially matters at higher baud rates. +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 + +# nRF52 <=> nRF91 interface pin 4 (see https://docs.nordicsemi.com/bundle/ug_nrf91_dk/page/UG/nrf91_DK/board_controller.html) +CONFIG_SLM_POWER_PIN=22 diff --git a/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.overlay b/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.overlay new file mode 100644 index 00000000000..249e680f23d --- /dev/null +++ b/applications/serial_lte_modem/overlay-zephyr-modem-nrf9160dk-nrf52840.overlay @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +/ { + chosen { + ncs,slm-uart = &uart1; + }; +}; + +&uart1 { + current-speed = <115200>; + hw-flow-control; +}; diff --git a/applications/serial_lte_modem/overlay-zephyr-modem.conf b/applications/serial_lte_modem/overlay-zephyr-modem.conf new file mode 100644 index 00000000000..5eda458a15e --- /dev/null +++ b/applications/serial_lte_modem/overlay-zephyr-modem.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# The nRF91 is power-managed by Zephyr's modem_cellular driver running on the other chip. +CONFIG_SLM_START_SLEEP=y + +CONFIG_SLM_CMUX_AUTOMATIC_FALLBACK_ON_PPP_STOPPAGE=y diff --git a/applications/serial_lte_modem/prj.conf b/applications/serial_lte_modem/prj.conf index 8a364158ac8..4e5cb6a364a 100644 --- a/applications/serial_lte_modem/prj.conf +++ b/applications/serial_lte_modem/prj.conf @@ -27,6 +27,7 @@ CONFIG_NET_NATIVE=n # Modem library CONFIG_NRF_MODEM_LIB=y +CONFIG_AT_CMD_CUSTOM=y # Align the max FD entry to NRF_MODEM_MAX_SOCKET_COUNT(8) CONFIG_POSIX_MAX_FDS=8 @@ -39,6 +40,7 @@ CONFIG_GPIO_NRFX=y # UART interface CONFIG_SERIAL=y +CONFIG_UART_USE_RUNTIME_CONFIGURE=y CONFIG_UART_ASYNC_API=y CONFIG_NRFX_TIMER2=y @@ -107,10 +109,10 @@ CONFIG_AT_MONITOR=y # CONFIG_SLM_CUSTOMER_VERSION="" CONFIG_SLM_EXTERNAL_XTAL=n -CONFIG_SLM_START_SLEEP=n -CONFIG_SLM_DATAMODE_URC=n -# Debug configurations +# debug options +#CONFIG_ASSERT=y +#CONFIG_LOG_BUFFER_SIZE=16384 #CONFIG_SLM_LOG_LEVEL_DBG=y #CONFIG_LOG_PRINTK=n #CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/applications/serial_lte_modem/sample.yaml b/applications/serial_lte_modem/sample.yaml index 550407ff5c7..740ab9dab93 100644 --- a/applications/serial_lte_modem/sample.yaml +++ b/applications/serial_lte_modem/sample.yaml @@ -3,7 +3,13 @@ sample: tests: applications.serial_lte_modem: build_only: true - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - nrf9131ek_nrf9131_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns @@ -12,7 +18,13 @@ tests: applications.serial_lte_modem.native_tls: build_only: true extra_args: EXTRA_CONF_FILE=overlay-native_tls.conf - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - nrf9131ek_nrf9131_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns @@ -21,7 +33,13 @@ tests: applications.serial_lte_modem.lwm2m_carrier: build_only: true extra_args: EXTRA_CONF_FILE=overlay-carrier.conf - platform_allow: nrf9160dk_nrf9160_ns nrf9161dk_nrf9161_ns thingy91_nrf9160_ns + platform_allow: + - nrf9160dk_nrf9160_ns + - nrf9161dk_nrf9161_ns + - nrf9151dk_nrf9151_ns + - nrf9131ek_nrf9131_ns + - thingy91_nrf9160_ns + - thingy91x_nrf9151_ns integration_platforms: - nrf9160dk_nrf9160_ns - nrf9161dk_nrf9161_ns diff --git a/applications/serial_lte_modem/src/ftp_c/slm_at_ftp.c b/applications/serial_lte_modem/src/ftp_c/slm_at_ftp.c index c7d35fdaeb0..2724be43763 100644 --- a/applications/serial_lte_modem/src/ftp_c/slm_at_ftp.c +++ b/applications/serial_lte_modem/src/ftp_c/slm_at_ftp.c @@ -23,87 +23,11 @@ LOG_MODULE_REGISTER(slm_ftp, CONFIG_SLM_LOG_LEVEL); #define FTP_PASSWORD_ANONYMOUS "anonymous@example.com" #define FTP_DEFAULT_PORT 21 -/**@brief Socketopt operations. */ -enum slm_ftp_operation { - /* FTP Session Management */ - FTP_OP_CLOSE, - FTP_OP_OPEN, - FTP_OP_STATUS, - FTP_OP_ASCII, - FTP_OP_BINARY, - FTP_OP_VERBOSE, - /* FTP Directory Operation */ - FTP_OP_PWD, - FTP_OP_LS, - FTP_OP_CD, - FTP_OP_MKDIR, - FTP_OP_RMDIR, - /* FTP File Operation */ - FTP_OP_RENAME, - FTP_OP_DELETE, - FTP_OP_GET, - FTP_OP_PUT, - FTP_OP_UPUT, - FTP_OP_MPUT, - /* count */ - FTP_OP_MAX -}; - -typedef int (*ftp_op_handler_t) (void); - -typedef struct ftp_op_list { - uint8_t op_code; - char *op_str; - ftp_op_handler_t handler; -} ftp_op_list_t; - static bool ftp_verbose_on; static char filepath[SLM_MAX_FILEPATH]; static int sz_filepath; static int (*ftp_data_mode_handler)(const uint8_t *data, int len, uint8_t flags); -/** forward declaration of cmd handlers **/ -static int do_ftp_close(void); -static int do_ftp_open(void); -static int do_ftp_status(void); -static int do_ftp_ascii(void); -static int do_ftp_binary(void); -static int do_ftp_verbose(void); - -static int do_ftp_pwd(void); -static int do_ftp_ls(void); -static int do_ftp_cd(void); -static int do_ftp_mkdir(void); -static int do_ftp_rmdir(void); - -static int do_ftp_rename(void); -static int do_ftp_delete(void); -static int do_ftp_get(void); -static int do_ftp_put(void); -static int do_ftp_uput(void); -static int do_ftp_mput(void); - -/**@brief SLM AT Command list type. */ -static ftp_op_list_t ftp_op_list[FTP_OP_MAX] = { - {FTP_OP_CLOSE, "close", do_ftp_close}, - {FTP_OP_OPEN, "open", do_ftp_open}, - {FTP_OP_STATUS, "status", do_ftp_status}, - {FTP_OP_ASCII, "ascii", do_ftp_ascii}, - {FTP_OP_BINARY, "binary", do_ftp_binary}, - {FTP_OP_VERBOSE, "verbose", do_ftp_verbose}, - {FTP_OP_PWD, "pwd", do_ftp_pwd}, - {FTP_OP_CD, "cd", do_ftp_cd}, - {FTP_OP_LS, "ls", do_ftp_ls}, - {FTP_OP_MKDIR, "mkdir", do_ftp_mkdir}, - {FTP_OP_RMDIR, "rmdir", do_ftp_rmdir}, - {FTP_OP_RENAME, "rename", do_ftp_rename}, - {FTP_OP_DELETE, "delete", do_ftp_delete}, - {FTP_OP_GET, "get", do_ftp_get}, - {FTP_OP_PUT, "put", do_ftp_put}, - {FTP_OP_UPUT, "uput", do_ftp_uput}, - {FTP_OP_MPUT, "mput", do_ftp_mput}, -}; - RING_BUF_DECLARE(ftp_data_buf, SLM_MAX_MESSAGE_SIZE); void ftp_ctrl_callback(const uint8_t *msg, uint16_t len) @@ -183,7 +107,9 @@ void ftp_data_callback(const uint8_t *msg, uint16_t len) /* AT#XFTP="open",,,[,[,]] */ /* similar to ftp://:@: */ -static int do_ftp_open(void) +SLM_AT_CMD_CUSTOM(xftp_open, "AT#XFTP=\"open\"", do_ftp_open); +static int do_ftp_open(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret = 0; char username[SLM_MAX_USERNAME] = ""; /* DO initialize, in case of login error */ @@ -194,31 +120,30 @@ static int do_ftp_open(void) int sz_hostname = sizeof(hostname); uint16_t port = FTP_DEFAULT_PORT; sec_tag_t sec_tag = INVALID_SEC_TAG; - int param_count = at_params_valid_count_get(&slm_at_param_list); /* Parse AT command */ - ret = util_string_get(&slm_at_param_list, 2, username, &sz_username); + ret = util_string_get(param_list, 2, username, &sz_username); if (ret || strlen(username) == 0) { strcpy(username, FTP_USER_ANONYMOUS); strcpy(password, FTP_PASSWORD_ANONYMOUS); } else { - ret = util_string_get(&slm_at_param_list, 3, password, &sz_password); + ret = util_string_get(param_list, 3, password, &sz_password); if (ret) { return -EINVAL; } } - ret = util_string_get(&slm_at_param_list, 4, hostname, &sz_hostname); + ret = util_string_get(param_list, 4, hostname, &sz_hostname); if (ret) { return ret; } if (param_count > 5) { - ret = at_params_unsigned_short_get(&slm_at_param_list, 5, &port); + ret = at_params_unsigned_short_get(param_list, 5, &port); if (ret) { return ret; } } if (param_count > 6) { - ret = at_params_unsigned_int_get(&slm_at_param_list, 6, &sec_tag); + ret = at_params_unsigned_int_get(param_list, 6, &sec_tag); if (ret) { return ret; } @@ -239,46 +164,46 @@ static int do_ftp_open(void) return 0; } -/* AT#XFTP="close" */ -static int do_ftp_close(void) +SLM_AT_CMD_CUSTOM(xftp_close, "AT#XFTP=\"close\"", do_ftp_close); +static int do_ftp_close(enum at_cmd_type, const struct at_param_list *, uint32_t) { int ret = ftp_close(); return (ret == FTP_CODE_221) ? 0 : -1; } -/* AT#XFTP="status" */ -static int do_ftp_status(void) +SLM_AT_CMD_CUSTOM(xftp_status, "AT#XFTP=\"status\"", do_ftp_status); +static int do_ftp_status(enum at_cmd_type, const struct at_param_list *, uint32_t) { int ret = ftp_status(); return (ret == FTP_CODE_211) ? 0 : -1; } -/* AT#XFTP="ascii" */ -static int do_ftp_ascii(void) +SLM_AT_CMD_CUSTOM(xftp_ascii, "AT#XFTP=\"ascii\"", do_ftp_ascii); +static int do_ftp_ascii(enum at_cmd_type, const struct at_param_list *, uint32_t) { int ret = ftp_type(FTP_TYPE_ASCII); return (ret == FTP_CODE_200) ? 0 : -1; } -/* AT#XFTP="binary" */ -static int do_ftp_binary(void) +SLM_AT_CMD_CUSTOM(xftp_binary, "AT#XFTP=\"binary\"", do_ftp_binary); +static int do_ftp_binary(enum at_cmd_type, const struct at_param_list *, uint32_t) { int ret = ftp_type(FTP_TYPE_BINARY); return (ret == FTP_CODE_200) ? 0 : -1; } -/* AT#XFTP="verbose","on|off" */ -static int do_ftp_verbose(void) +SLM_AT_CMD_CUSTOM(xftp_verbose, "AT#XFTP=\"verbose\"", do_ftp_verbose); +static int do_ftp_verbose(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret = 0; char vb_mode[4]; int sz_mode = 4; - ret = util_string_get(&slm_at_param_list, 2, vb_mode, &sz_mode); + ret = util_string_get(param_list, 2, vb_mode, &sz_mode); if (ret) { return ret; } @@ -296,8 +221,8 @@ static int do_ftp_verbose(void) return 0; } -/* AT#XFTP="pwd" */ -static int do_ftp_pwd(void) +SLM_AT_CMD_CUSTOM(xftp_pwd, "AT#XFTP=\"pwd\"", do_ftp_pwd); +static int do_ftp_pwd(enum at_cmd_type, const struct at_param_list *, uint32_t) { int ret = ftp_pwd(); @@ -305,15 +230,15 @@ static int do_ftp_pwd(void) } /* AT#XFTP="ls"[,[,]] */ -static int do_ftp_ls(void) +SLM_AT_CMD_CUSTOM(xftp_ls, "AT#XFTP=\"ls\"", do_ftp_ls); +static int do_ftp_ls(enum at_cmd_type, const struct at_param_list *param_list, uint32_t param_count) { int ret; char options[FTP_MAX_OPTION] = ""; int sz_options = FTP_MAX_OPTION; - int param_count = at_params_valid_count_get(&slm_at_param_list); if (param_count > 2) { - ret = util_string_get(&slm_at_param_list, 2, options, &sz_options); + ret = util_string_get(param_list, 2, options, &sz_options); if (ret) { return ret; } @@ -321,7 +246,7 @@ static int do_ftp_ls(void) memset(filepath, 0x00, SLM_MAX_FILEPATH); sz_filepath = SLM_MAX_FILEPATH; if (param_count > 3) { - ret = util_string_get(&slm_at_param_list, 3, filepath, &sz_filepath); + ret = util_string_get(param_list, 3, filepath, &sz_filepath); if (ret) { return ret; } @@ -337,13 +262,13 @@ static int do_ftp_ls(void) } } -/* AT#XFTP="cd", */ -static int do_ftp_cd(void) +SLM_AT_CMD_CUSTOM(xftp_cd, "AT#XFTP=\"cd\"", do_ftp_cd); +static int do_ftp_cd(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } @@ -352,13 +277,13 @@ static int do_ftp_cd(void) return (ret == FTP_CODE_250) ? 0 : -1; } -/* AT#XFTP="mkdir", */ -static int do_ftp_mkdir(void) +SLM_AT_CMD_CUSTOM(xftp_mkdir, "AT#XFTP=\"mkdir\"", do_ftp_mkdir); +static int do_ftp_mkdir(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } @@ -367,13 +292,13 @@ static int do_ftp_mkdir(void) return (ret == FTP_CODE_257) ? 0 : -1; } -/* AT#XFTP="rmdir", */ -static int do_ftp_rmdir(void) +SLM_AT_CMD_CUSTOM(xftp_rmdir, "AT#XFTP=\"rmdir\"", do_ftp_rmdir); +static int do_ftp_rmdir(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } @@ -382,19 +307,19 @@ static int do_ftp_rmdir(void) return (ret == FTP_CODE_250) ? 0 : -1; } -/* AT#XFTP="rename",, */ -static int do_ftp_rename(void) +SLM_AT_CMD_CUSTOM(xftp_rename, "AT#XFTP=\"rename\"", do_ftp_rename); +static int do_ftp_rename(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; char file_new[SLM_MAX_FILEPATH]; int sz_file_new = SLM_MAX_FILEPATH; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } - ret = util_string_get(&slm_at_param_list, 3, file_new, &sz_file_new); + ret = util_string_get(param_list, 3, file_new, &sz_file_new); if (ret) { return ret; } @@ -403,13 +328,13 @@ static int do_ftp_rename(void) return (ret == FTP_CODE_250) ? 0 : -1; } -/* AT#XFTP="delete", */ -static int do_ftp_delete(void) +SLM_AT_CMD_CUSTOM(xftp_delete, "AT#XFTP=\"delete\"", do_ftp_delete); +static int do_ftp_delete(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } @@ -418,13 +343,13 @@ static int do_ftp_delete(void) return (ret == FTP_CODE_250) ? 0 : -1; } -/* AT#XFTP="get", */ -static int do_ftp_get(void) +SLM_AT_CMD_CUSTOM(xftp_get, "AT#XFTP=\"get\"", do_ftp_get); +static int do_ftp_get(enum at_cmd_type, const struct at_param_list *param_list, uint32_t) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } @@ -475,18 +400,19 @@ static int ftp_put_handler(const uint8_t *data, int len, uint8_t flags) return (ret == FTP_CODE_226) ? 0 : -1; } -/* AT#XFTP="put",[,] */ -static int do_ftp_put(void) +SLM_AT_CMD_CUSTOM(xftp_put, "AT#XFTP=\"put\"", do_ftp_put); +static int do_ftp_put(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } - if (at_params_valid_count_get(&slm_at_param_list) == 3) { + if (param_count == 3) { /* enter data mode */ ret = enter_datamode(ftp_datamode_callback); if (ret) { @@ -498,7 +424,7 @@ static int do_ftp_put(void) int size = sizeof(data); int err; - err = util_string_get(&slm_at_param_list, 3, data, &size); + err = util_string_get(param_list, 3, data, &size); if (err) { return err; } @@ -527,12 +453,13 @@ static int ftp_uput_handler(const uint8_t *data, int len, uint8_t flags) return (ret == FTP_CODE_226) ? 0 : -1; } -/* AT#XFTP="uput"[,] */ -static int do_ftp_uput(void) +SLM_AT_CMD_CUSTOM(xftp_uput, "AT#XFTP=\"uput\"", do_ftp_uput); +static int do_ftp_uput(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret = -1; - if (at_params_valid_count_get(&slm_at_param_list) == 2) { + if (param_count == 2) { /* enter data mode */ ret = enter_datamode(ftp_datamode_callback); if (ret) { @@ -544,7 +471,7 @@ static int do_ftp_uput(void) int size = sizeof(data); int err; - err = util_string_get(&slm_at_param_list, 2, data, &size); + err = util_string_get(param_list, 2, data, &size); if (err) { return err; } @@ -569,18 +496,19 @@ static int ftp_mput_handler(const uint8_t *data, int len, uint8_t flags) return (ret == FTP_CODE_226) ? 0 : -1; } -/* AT#XFTP="mput",[,] */ -static int do_ftp_mput(void) +SLM_AT_CMD_CUSTOM(xftp_mput, "AT#XFTP=\"mput\"", do_ftp_mput); +static int do_ftp_mput(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret; sz_filepath = SLM_MAX_FILEPATH; - ret = util_string_get(&slm_at_param_list, 2, filepath, &sz_filepath); + ret = util_string_get(param_list, 2, filepath, &sz_filepath); if (ret) { return ret; } - if (at_params_valid_count_get(&slm_at_param_list) == 3) { + if (param_count == 3) { /* enter data mode */ ret = enter_datamode(ftp_datamode_callback); if (ret) { @@ -592,7 +520,7 @@ static int do_ftp_mput(void) int size = sizeof(data); int err; - err = util_string_get(&slm_at_param_list, 3, data, &size); + err = util_string_get(param_list, 3, data, &size); if (err) { return err; } @@ -603,32 +531,6 @@ static int do_ftp_mput(void) return ret; } -/**@brief API to handle FTP AT command - */ -int handle_at_ftp(enum at_cmd_type cmd_type) -{ - int ret; - char op_str[16]; - int size = 16; - - if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { - return -EINVAL; - } - ret = util_string_get(&slm_at_param_list, 1, op_str, &size); - if (ret) { - return ret; - } - ret = -EINVAL; - for (int i = 0; i < FTP_OP_MAX; i++) { - if (slm_util_casecmp(op_str, ftp_op_list[i].op_str)) { - ret = ftp_op_list[i].handler(); - break; - } - } - - return ret; -} - /**@brief API to initialize FTP AT commands handler */ int slm_at_ftp_init(void) diff --git a/applications/serial_lte_modem/src/ftp_c/slm_at_tftp.c b/applications/serial_lte_modem/src/ftp_c/slm_at_tftp.c index 1b31f3261c6..6aa3f2017d5 100644 --- a/applications/serial_lte_modem/src/ftp_c/slm_at_tftp.c +++ b/applications/serial_lte_modem/src/ftp_c/slm_at_tftp.c @@ -50,8 +50,7 @@ static int do_tftp_get(int family, const char *server, uint16_t port, const char struct tftpc client = { .callback = tftp_callback }; - ret = util_resolve_host(0, server, port, family, - Z_LOG_OBJECT_PTR(slm_tftp), &client.server); + ret = util_resolve_host(0, server, port, family, &client.server); if (ret) { return -EAGAIN; } @@ -94,8 +93,7 @@ static int do_tftp_put(int family, const char *server, uint16_t port, const char .callback = tftp_callback }; - ret = util_resolve_host(0, server, port, family, - Z_LOG_OBJECT_PTR(slm_tftp), &client.server); + ret = util_resolve_host(0, server, port, family, &client.server); if (ret) { return -EAGAIN; } @@ -130,8 +128,9 @@ static int do_tftp_put(int family, const char *server, uint16_t port, const char return ret; } -/* Handles AT#XTFTP commands. */ -int handle_at_tftp(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtftp, "AT#XTFTP", handle_at_tftp); +static int handle_at_tftp(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; @@ -140,32 +139,31 @@ int handle_at_tftp(enum at_cmd_type cmd_type) char filepath[SLM_MAX_FILEPATH]; char mode[16]; /** "netascii", "octet", "mail" */ int size; - int param_count = at_params_valid_count_get(&slm_at_param_list); switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } size = sizeof(url); - err = util_string_get(&slm_at_param_list, 2, url, &size); + err = util_string_get(param_list, 2, url, &size); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &port); + err = at_params_unsigned_short_get(param_list, 3, &port); if (err) { return err; } size = sizeof(filepath); - err = util_string_get(&slm_at_param_list, 4, filepath, &size); + err = util_string_get(param_list, 4, filepath, &size); if (err) { return err; } if (param_count > 5) { size = sizeof(mode); - err = util_string_get(&slm_at_param_list, 5, mode, &size); + err = util_string_get(param_list, 5, mode, &size); if (err) { return err; } @@ -186,7 +184,7 @@ int handle_at_tftp(enum at_cmd_type cmd_type) uint8_t data[SLM_MAX_PAYLOAD_SIZE + 1] = {0}; size = sizeof(data); - err = util_string_get(&slm_at_param_list, 6, data, &size); + err = util_string_get(param_list, 6, data, &size); if (err) { return err; } diff --git a/applications/serial_lte_modem/src/gnss/slm_at_gnss.c b/applications/serial_lte_modem/src/gnss/slm_at_gnss.c index f6901e67a0e..88d9564ed5b 100644 --- a/applications/serial_lte_modem/src/gnss/slm_at_gnss.c +++ b/applications/serial_lte_modem/src/gnss/slm_at_gnss.c @@ -127,7 +127,7 @@ static void gnss_status_set(enum gnss_status status) /* A notification is sent when the GNSS status is updated. * However this gets called in interrupt context (from gnss_event_handler()), * from which UART messages cannot be sent. This task is thus delegated - * to a worker, to which the the new GNSS status is passed. + * to a worker, to which the new GNSS status is passed. * A FIFO rather than a single variable is used to not miss GNSS status changes * in case they happen twice (or more) before the worker had the time to process them. */ @@ -502,8 +502,8 @@ static void fix_rep_wk(struct k_work *work) /* GIS accuracy: http://wiki.gis.com/wiki/index.php/Decimal_degrees, use default .6lf */ rsp_send("\r\n#XGPS: %lf,%lf,%f,%f,%f,%f,\"%04u-%02u-%02u %02u:%02u:%02u\"\r\n", - pvt.latitude, pvt.longitude, pvt.altitude, - pvt.accuracy, pvt.speed, pvt.heading, + pvt.latitude, pvt.longitude, (double)pvt.altitude, + (double)pvt.accuracy, (double)pvt.speed, (double)pvt.heading, pvt.datetime.year, pvt.datetime.month, pvt.datetime.day, pvt.datetime.hour, pvt.datetime.minute, pvt.datetime.seconds); @@ -601,14 +601,15 @@ static void gnss_event_handler(int event) } } -/* Handles AT#XGPS commands. */ -int handle_at_gps(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xgps_set, "AT#XGPS=", handle_at_gps); +SLM_AT_CMD_CUSTOM(xgps_read, "AT#XGPS?", handle_at_gps); +static int handle_at_gps(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; uint16_t interval; uint16_t timeout; - uint32_t param_count; enum { OP_IDX = 1, @@ -619,8 +620,7 @@ int handle_at_gps(enum at_cmd_type cmd_type) }; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - param_count = at_params_valid_count_get(&slm_at_param_list); - err = at_params_unsigned_short_get(&slm_at_param_list, OP_IDX, &op); + err = at_params_unsigned_short_get(param_list, OP_IDX, &op); if (err) { return err; } @@ -631,7 +631,7 @@ int handle_at_gps(enum at_cmd_type cmd_type) } err = at_params_unsigned_short_get( - &slm_at_param_list, CLOUD_ASSISTANCE_IDX, &gnss_cloud_assistance); + param_list, CLOUD_ASSISTANCE_IDX, &gnss_cloud_assistance); if (err || gnss_cloud_assistance > 1) { return -EINVAL; } @@ -652,8 +652,7 @@ int handle_at_gps(enum at_cmd_type cmd_type) return -ENOTCONN; } - err = at_params_unsigned_short_get( - &slm_at_param_list, INTERVAL_IDX, &interval); + err = at_params_unsigned_short_get(param_list, INTERVAL_IDX, &interval); if (err || (interval > 1 && interval < 10)) { return -EINVAL; } @@ -687,7 +686,7 @@ int handle_at_gps(enum at_cmd_type cmd_type) timeout = 60; /* default value */ } else { err = at_params_unsigned_short_get( - &slm_at_param_list, TIMEOUT_IDX, &timeout); + param_list, TIMEOUT_IDX, &timeout); if (err || param_count != MAX_PARAM_COUNT) { return -EINVAL; } @@ -731,15 +730,16 @@ int handle_at_gps(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XGPSDEL commands. */ -int handle_at_gps_delete(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xgpsdel, "AT#XGPSDEL", handle_at_gps_delete); +static int handle_at_gps_delete(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint32_t mask; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_int_get(&slm_at_param_list, 1, &mask); + err = at_params_unsigned_int_get(param_list, 1, &mask); if (err || !mask || (mask & NRF_MODEM_GNSS_DELETE_TCXO_OFFSET)) { return -EINVAL; } diff --git a/applications/serial_lte_modem/src/gpio/slm_at_gpio.c b/applications/serial_lte_modem/src/gpio/slm_at_gpio.c index 51463e28d52..e8e78046d96 100644 --- a/applications/serial_lte_modem/src/gpio/slm_at_gpio.c +++ b/applications/serial_lte_modem/src/gpio/slm_at_gpio.c @@ -192,20 +192,21 @@ static int do_gpio_pin_operate(uint16_t op, gpio_pin_t pin, uint16_t value) return 0; } -/* Handles AT#XGPIOCFG commands. */ -int handle_at_gpio_configure(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xgpiocfg, "AT#XGPIOCFG", handle_at_gpio_configure); +static int handle_at_gpio_configure(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t) { int err = -EINVAL; uint16_t pin = 0xff, op = 0xff; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err < 0) { LOG_ERR("Fail to get op: %d", err); return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &pin); + err = at_params_unsigned_short_get(param_list, 2, &pin); if (err < 0) { LOG_ERR("Fail to get pin: %d", err); return err; @@ -223,15 +224,17 @@ int handle_at_gpio_configure(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XGPIO command. */ -int handle_at_gpio_operate(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xgpio_set, "AT#XGPIO=", handle_at_gpio_operate); +SLM_AT_CMD_CUSTOM(xgpio_read, "AT#XGPIO?", handle_at_gpio_operate); +static int handle_at_gpio_operate(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint16_t pin = 0xff, op = 0xff, value = 0xff; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err < 0) { LOG_ERR("Fail to get OP code: %d", err); return err; @@ -240,7 +243,7 @@ int handle_at_gpio_operate(enum at_cmd_type cmd_type) LOG_ERR("GPIO OP code is out of range: %d", op); return -EINVAL; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &pin); + err = at_params_unsigned_short_get(param_list, 2, &pin); if (err < 0) { LOG_ERR("Fail to get pin: %d", err); return err; @@ -250,7 +253,7 @@ int handle_at_gpio_operate(enum at_cmd_type cmd_type) return -EINVAL; } if (op == SLM_GPIO_OP_WRITE) { - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &value); + err = at_params_unsigned_short_get(param_list, 3, &value); if (err < 0) { LOG_ERR("Fail to get value: %d", err); return err; diff --git a/applications/serial_lte_modem/src/http_c/slm_at_httpc.c b/applications/serial_lte_modem/src/http_c/slm_at_httpc.c index de389d46828..590439f9bb9 100644 --- a/applications/serial_lte_modem/src/http_c/slm_at_httpc.c +++ b/applications/serial_lte_modem/src/http_c/slm_at_httpc.c @@ -14,7 +14,9 @@ #include "slm_at_host.h" #include "slm_at_httpc.h" #include "slm_util.h" +#if defined(CONFIG_SLM_NATIVE_TLS) #include "slm_native_tls.h" +#endif LOG_MODULE_REGISTER(slm_httpc, CONFIG_SLM_LOG_LEVEL); @@ -222,16 +224,7 @@ static int do_http_connect(void) if (httpc.sec_tag == INVALID_SEC_TAG) { ret = socket(httpc.family, SOCK_STREAM, IPPROTO_TCP); } else { -#if defined(CONFIG_SLM_NATIVE_TLS) - ret = slm_tls_loadcrdl(httpc.sec_tag); - if (ret < 0) { - LOG_ERR("Fail to load credential: %d", ret); - return -EAGAIN; - } - ret = socket(httpc.family, SOCK_STREAM | SOCK_NATIVE_TLS, IPPROTO_TLS_1_2); -#else ret = socket(httpc.family, SOCK_STREAM, IPPROTO_TLS_1_2); -#endif } if (ret < 0) { LOG_ERR("socket() failed: %d", -errno); @@ -240,20 +233,22 @@ static int do_http_connect(void) httpc.fd = ret; /* Set socket options */ - LOG_DBG("Configuring socket timeout (%lld s)", timeo.tv_sec); - ret = setsockopt(httpc.fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)); - if (ret) { - LOG_ERR("setsockopt(SO_SNDTIMEO) error: %d", -errno); - ret = -errno; - goto exit_cli; - } - ret = setsockopt(httpc.fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); - if (ret) { - LOG_ERR("setsockopt(SO_SNDTIMEO) error: %d", -errno); - ret = -errno; - goto exit_cli; - } if (httpc.sec_tag != INVALID_SEC_TAG) { +#if defined(CONFIG_SLM_NATIVE_TLS) + ret = slm_native_tls_load_credentials(httpc.sec_tag); + if (ret < 0) { + LOG_ERR("Failed to load sec tag: %d (%d)", httpc.sec_tag, ret); + goto exit_cli; + } + int tls_native = 1; + + /* Must be the first socket option to set. */ + ret = setsockopt(httpc.fd, SOL_TLS, TLS_NATIVE, &tls_native, sizeof(tls_native)); + if (ret) { + ret = errno; + goto exit_cli; + } +#endif sec_tag_t sec_tag_list[] = { httpc.sec_tag }; ret = setsockopt(httpc.fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, @@ -294,9 +289,22 @@ static int do_http_connect(void) #endif } + LOG_DBG("Configuring socket timeout (%lld s)", timeo.tv_sec); + ret = setsockopt(httpc.fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)); + if (ret) { + LOG_ERR("setsockopt(SO_SNDTIMEO) error: %d", -errno); + ret = -errno; + goto exit_cli; + } + ret = setsockopt(httpc.fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); + if (ret) { + LOG_ERR("setsockopt(SO_SNDTIMEO) error: %d", -errno); + ret = -errno; + goto exit_cli; + } + /* Connect to HTTP server */ - ret = util_resolve_host(0, httpc.host, httpc.port, httpc.family, - Z_LOG_OBJECT_PTR(slm_httpc), &sa); + ret = util_resolve_host(0, httpc.host, httpc.port, httpc.family, &sa); if (ret) { goto exit_cli; } @@ -316,12 +324,6 @@ static int do_http_connect(void) return 0; exit_cli: -#if defined(CONFIG_SLM_NATIVE_TLS) - if (httpc.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(httpc.sec_tag); - httpc.sec_tag = INVALID_SEC_TAG; - } -#endif close(httpc.fd); httpc.fd = INVALID_SOCKET; rsp_send("\r\n#XHTTPCCON: 0\r\n"); @@ -335,12 +337,6 @@ static int do_http_disconnect(void) if (httpc.fd == INVALID_SOCKET) { return 0; } -#if defined(CONFIG_SLM_NATIVE_TLS) - if (httpc.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(httpc.sec_tag); - httpc.sec_tag = INVALID_SEC_TAG; - } -#endif int ret = close(httpc.fd); if (ret) { @@ -421,8 +417,9 @@ static int do_http_request(void) return err; } -/* Handles AT#XHTTPCCON commands. */ -int handle_at_httpc_connect(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xhttpccon, "AT#XHTTPCCON", handle_at_httpc_connect); +static int handle_at_httpc_connect(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err = -EINVAL; uint16_t op; @@ -430,31 +427,28 @@ int handle_at_httpc_connect(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } if (op == HTTPC_CONNECT || op == HTTPC_CONNECT6) { - err = util_string_get(&slm_at_param_list, 2, httpc.host, &host_sz); + err = util_string_get(param_list, 2, httpc.host, &host_sz); if (err) { return err; } - if (at_params_unsigned_short_get(&slm_at_param_list, 3, &httpc.port)) { + if (at_params_unsigned_short_get(param_list, 3, &httpc.port)) { return -EINVAL; } - const int param_count = at_params_valid_count_get(&slm_at_param_list); httpc.sec_tag = INVALID_SEC_TAG; if (param_count > 4) { - if (at_params_unsigned_int_get(&slm_at_param_list, 4, - &httpc.sec_tag)) { + if (at_params_unsigned_int_get(param_list, 4, &httpc.sec_tag)) { return -EINVAL; } } httpc.peer_verify = TLS_PEER_VERIFY_REQUIRED; if (param_count > 5) { - if (at_params_unsigned_int_get(&slm_at_param_list, 5, - &httpc.peer_verify) || + if (at_params_unsigned_int_get(param_list, 5, &httpc.peer_verify) || (httpc.peer_verify != TLS_PEER_VERIFY_NONE && httpc.peer_verify != TLS_PEER_VERIFY_OPTIONAL && httpc.peer_verify != TLS_PEER_VERIFY_REQUIRED)) { @@ -465,8 +459,7 @@ int handle_at_httpc_connect(enum at_cmd_type cmd_type) if (param_count > 6) { uint16_t hostname_verify; - if (at_params_unsigned_short_get(&slm_at_param_list, 6, - &hostname_verify) || + if (at_params_unsigned_short_get(param_list, 6, &hostname_verify) || (hostname_verify != 0 && hostname_verify != 1)) { return -EINVAL; } @@ -573,11 +566,11 @@ static int http_headers_preprocess(size_t size) return 0; } -/* Handles AT#XHTTPCREQ commands. */ -int handle_at_httpc_request(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xhttpcreq, "AT#XHTTPCREQ", handle_at_httpc_request); +static int handle_at_httpc_request(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err = -EINVAL; - int param_count; int size; size_t offset; @@ -591,7 +584,7 @@ int handle_at_httpc_request(enum at_cmd_type cmd_type) memset(slm_data_buf, 0, sizeof(slm_data_buf)); /* Get method string */ size = HTTPC_METHOD_LEN; - err = util_string_get(&slm_at_param_list, 1, slm_data_buf, &size); + err = util_string_get(param_list, 1, slm_data_buf, &size); if (err < 0) { LOG_ERR("Fail to get method string: %d", err); return err; @@ -600,19 +593,18 @@ int handle_at_httpc_request(enum at_cmd_type cmd_type) offset = size + 1; /* Get resource path string */ size = HTTPC_RES_LEN; - err = util_string_get(&slm_at_param_list, 2, slm_data_buf + offset, &size); + err = util_string_get(param_list, 2, slm_data_buf + offset, &size); if (err < 0) { LOG_ERR("Fail to get resource string: %d", err); return err; } httpc.resource = (char *)(slm_data_buf + offset); - param_count = at_params_valid_count_get(&slm_at_param_list); httpc.headers = NULL; if (param_count >= 4) { /* Get headers string */ offset += size + 1; size = HTTPC_HEADERS_LEN; - err = util_string_get(&slm_at_param_list, 3, slm_data_buf + offset, &size); + err = util_string_get(param_list, 3, slm_data_buf + offset, &size); if (err == 0 && size > 0) { httpc.headers = (char *)(slm_data_buf + offset); err = http_headers_preprocess(size); @@ -628,13 +620,12 @@ int handle_at_httpc_request(enum at_cmd_type cmd_type) /* Get content type string */ offset += size + 1; size = HTTPC_CONTEN_TYPE_LEN; - err = util_string_get(&slm_at_param_list, 4, slm_data_buf + offset, &size); + err = util_string_get(param_list, 4, slm_data_buf + offset, &size); if (err == 0 && size > 0) { httpc.content_type = (char *)(slm_data_buf + offset); } /* Get content length */ - err = at_params_unsigned_int_get( - &slm_at_param_list, 5, &httpc.content_length); + err = at_params_unsigned_int_get(param_list, 5, &httpc.content_length); if (err != 0) { return err; } @@ -642,7 +633,7 @@ int handle_at_httpc_request(enum at_cmd_type cmd_type) uint16_t tmp; /* Get chunked transfer flag */ - err = at_params_unsigned_short_get(&slm_at_param_list, 6, &tmp); + err = at_params_unsigned_short_get(param_list, 6, &tmp); if (err != 0) { return err; } diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig b/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig index b2277a33c07..5b31f0c2b11 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig +++ b/applications/serial_lte_modem/src/lwm2m_carrier/Kconfig @@ -11,11 +11,11 @@ config SLM_CARRIER if SLM_CARRIER config SLM_CARRIER_APP_DATA_BUFFER_LEN - int "Size of the buffer for sending application data" - default 512 + int "Size of the buffer for setting application data" + default 768 + range 128 768 help - Specifies maximum application data size to be sent to the server - through the App Data Container, the Binary App Data Container or - the Event Log objects. + Specifies maximum application data size to be set in the App Data Container, + the Binary App Data Container or the Event Log objects. endif # SLM_CARRIER diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c index 6051d1220aa..68436ff2c0c 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c +++ b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c @@ -17,93 +17,10 @@ LOG_MODULE_REGISTER(slm_carrier, CONFIG_SLM_LOG_LEVEL); -/**@brief LwM2M Carrier operations. */ -enum slm_carrier_operation { - /* Carrier AppData Operation */ - CARRIER_OP_APPDATA_SEND, - /* Carrier Device Operation */ - CARRIER_OP_DEVICE_BATTERY_LEVEL, - CARRIER_OP_DEVICE_BATTERY_STATUS, - CARRIER_OP_DEVICE_CURRENT, - CARRIER_OP_DEVICE_ERROR, - CARRIER_OP_DEVICE_MEM_TOTAL, - CARRIER_OP_DEVICE_MEM_FREE, - CARRIER_OP_DEVICE_POWER_SOURCES, - CARRIER_OP_DEVICE_TIMEZONE, - CARRIER_OP_DEVICE_TIME, - CARRIER_OP_DEVICE_UTC_OFFSET, - CARRIER_OP_DEVICE_UTC_TIME, - CARRIER_OP_DEVICE_VOLTAGE, - /* Carrier Event Log Operation */ - CARRIER_OP_EVENT_LOG_LOG_DATA, - /* Carrier Location Operation */ - CARRIER_OP_LOCATION_POSITION, - CARRIER_OP_LOCATION_VELOCITY, - /* Carrier Portfolio Operation */ - CARRIER_OP_PORTFOLIO, - /* Carrier Request Operation */ - CARRIER_OP_REQUEST_REBOOT, - CARRIER_OP_REQUEST_LINK_DOWN, - CARRIER_OP_REQUEST_LINK_UP, - /* Count */ - CARRIER_OP_MAX -}; - -struct carrier_op_list { - uint8_t op_code; - char *op_str; - int (*handler)(void); -}; /* Static variable to report the memory free resource. */ static int m_mem_free; -/** forward declaration of cmd handlers **/ -static int do_carrier_appdata_send(void); -static int do_carrier_device_battery_level(void); -static int do_carrier_device_battery_status(void); -static int do_carrier_device_current(void); -static int do_carrier_device_error(void); -static int do_carrier_device_mem_total(void); -static int do_carrier_device_mem_free(void); -static int do_carrier_device_power_sources(void); -static int do_carrier_device_timezone(void); -static int do_carrier_device_time(void); -static int do_carrier_device_utc_offset(void); -static int do_carrier_device_utc_time(void); -static int do_carrier_device_voltage(void); -static int do_carrier_event_log_log_data(void); -static int do_carrier_location_position(void); -static int do_carrier_location_velocity(void); -static int do_carrier_portfolio(void); -static int do_carrier_request_reboot(void); -static int do_carrier_request_link_down(void); -static int do_carrier_request_link_up(void); - -/**@brief SLM Carrier AT Command list type. */ -static struct carrier_op_list op_list[CARRIER_OP_MAX] = { - {CARRIER_OP_APPDATA_SEND, "app_data", do_carrier_appdata_send}, - {CARRIER_OP_DEVICE_BATTERY_LEVEL, "battery_level", do_carrier_device_battery_level}, - {CARRIER_OP_DEVICE_BATTERY_STATUS, "battery_status", do_carrier_device_battery_status}, - {CARRIER_OP_DEVICE_CURRENT, "current", do_carrier_device_current}, - {CARRIER_OP_DEVICE_ERROR, "error", do_carrier_device_error}, - {CARRIER_OP_DEVICE_MEM_TOTAL, "memory_total", do_carrier_device_mem_total}, - {CARRIER_OP_DEVICE_MEM_FREE, "memory_free", do_carrier_device_mem_free}, - {CARRIER_OP_DEVICE_POWER_SOURCES, "power_sources", do_carrier_device_power_sources}, - {CARRIER_OP_DEVICE_TIMEZONE, "timezone", do_carrier_device_timezone}, - {CARRIER_OP_DEVICE_TIME, "time", do_carrier_device_time}, - {CARRIER_OP_DEVICE_UTC_OFFSET, "utc_offset", do_carrier_device_utc_offset}, - {CARRIER_OP_DEVICE_UTC_TIME, "utc_time", do_carrier_device_utc_time}, - {CARRIER_OP_DEVICE_VOLTAGE, "voltage", do_carrier_device_voltage}, - {CARRIER_OP_EVENT_LOG_LOG_DATA, "log_data", do_carrier_event_log_log_data}, - {CARRIER_OP_LOCATION_POSITION, "position", do_carrier_location_position}, - {CARRIER_OP_LOCATION_VELOCITY, "velocity", do_carrier_location_velocity}, - {CARRIER_OP_PORTFOLIO, "portfolio", do_carrier_portfolio}, - {CARRIER_OP_REQUEST_REBOOT, "reboot", do_carrier_request_reboot}, - {CARRIER_OP_REQUEST_LINK_DOWN, "link_down", do_carrier_request_link_down}, - {CARRIER_OP_REQUEST_LINK_UP, "link_up", do_carrier_request_link_up}, -}; - #define SLM_CARRIER_OP_STR_MAX (sizeof("battery_status") + 1) struct k_work_delayable reconnect_work; @@ -254,6 +171,9 @@ int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event) /* Return -1 to defer the reboot until the application decides to do so. */ err = -1; break; + case LWM2M_CARRIER_EVENT_MODEM_DOMAIN: + LOG_DBG("LWM2M_CARRIER_EVENT_MODEM_DOMAIN"); + break; case LWM2M_CARRIER_EVENT_APP_DATA: LOG_DBG("LWM2M_CARRIER_EVENT_APP_DATA"); on_event_app_data(event); @@ -276,7 +196,7 @@ int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event) return err; } -/* Carrier App Data Send data mode handler */ +/* Carrier App Data Set data mode handler */ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, uint8_t flags) { int ret = 0; @@ -290,7 +210,7 @@ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, u uint16_t path[3] = { LWM2M_CARRIER_OBJECT_APP_DATA_CONTAINER, 0, 0 }; uint8_t path_len = 3; - ret = lwm2m_carrier_app_data_send(path, path_len, data, len); + ret = lwm2m_carrier_app_data_set(path, path_len, data, len); LOG_INF("datamode send: %d", ret); if (ret < 0) { (void)exit_datamode_handler(ret); @@ -302,13 +222,13 @@ static int carrier_datamode_callback(uint8_t op, const uint8_t *data, int len, u return ret; } -/* AT#XCARRIER="app_data"[,][,,] */ -static int do_carrier_appdata_send(void) +/* AT#XCARRIER="app_data_set"[,][,,] */ +SLM_AT_CMD_CUSTOM(xcarrier_app_data_set, "AT#XCARRIER=\"app_data_set\"", do_carrier_appdata_set); +static int do_carrier_appdata_set(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret = 0; - uint32_t param_count = at_params_valid_count_get(&slm_at_param_list); - if (param_count == 2) { /* enter data mode */ ret = enter_datamode(carrier_datamode_callback); @@ -322,12 +242,12 @@ static int do_carrier_appdata_send(void) uint16_t path[3] = { LWM2M_CARRIER_OBJECT_APP_DATA_CONTAINER, 0, 0 }; uint8_t path_len = 3; - ret = util_string_get(&slm_at_param_list, 2, data, &size); + ret = util_string_get(param_list, 2, data, &size); if (ret) { return ret; } - ret = lwm2m_carrier_app_data_send(path, path_len, data, size); + ret = lwm2m_carrier_app_data_set(path, path_len, data, size); } else if (param_count == 4 || param_count == 5) { uint8_t *data = NULL; char buffer[CONFIG_SLM_CARRIER_APP_DATA_BUFFER_LEN] = {0}; @@ -336,12 +256,12 @@ static int do_carrier_appdata_send(void) uint16_t inst_id; uint16_t res_inst_id; - ret = at_params_unsigned_short_get(&slm_at_param_list, param_count - 2, &inst_id); + ret = at_params_unsigned_short_get(param_list, param_count - 2, &inst_id); if (ret) { return ret; } - ret = at_params_unsigned_short_get(&slm_at_param_list, param_count - 1, + ret = at_params_unsigned_short_get(param_list, param_count - 1, &res_inst_id); if (ret) { return ret; @@ -354,7 +274,7 @@ static int do_carrier_appdata_send(void) if (param_count == 5) { size = CONFIG_SLM_CARRIER_APP_DATA_BUFFER_LEN; - ret = util_string_get(&slm_at_param_list, 2, buffer, &size); + ret = util_string_get(param_list, 2, buffer, &size); if (ret) { return ret; } @@ -362,19 +282,22 @@ static int do_carrier_appdata_send(void) data = buffer; } - ret = lwm2m_carrier_app_data_send(path, path_len, data, size); + ret = lwm2m_carrier_app_data_set(path, path_len, data, size); } return ret; } /* AT#XCARRIER="battery_level", */ -static int do_carrier_device_battery_level(void) +SLM_AT_CMD_CUSTOM(xcarrier_battery_level, "AT#XCARRIER=\"battery_level\"", + do_carrier_device_battery_level); +static int do_carrier_device_battery_level(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret; uint16_t battery_level; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &battery_level); + ret = at_params_unsigned_short_get(param_list, 2, &battery_level); if (ret) { return ret; } @@ -383,11 +306,14 @@ static int do_carrier_device_battery_level(void) } /* AT#XCARRIER="battery_status", */ -static int do_carrier_device_battery_status(void) +SLM_AT_CMD_CUSTOM(xcarrier_battery_status, "AT#XCARRIER=\"battery_status\"", + do_carrier_device_battery_status); +static int do_carrier_device_battery_status(enum at_cmd_type, + const struct at_param_list *param_list, uint32_t) { int ret, battery_status; - ret = at_params_int_get(&slm_at_param_list, 2, &battery_status); + ret = at_params_int_get(param_list, 2, &battery_status); if (ret) { return ret; } @@ -396,17 +322,19 @@ static int do_carrier_device_battery_status(void) } /* AT#XCARRIER="current",, */ -static int do_carrier_device_current(void) +SLM_AT_CMD_CUSTOM(xcarrier_current, "AT#XCARRIER=\"current\"", do_carrier_device_current); +static int do_carrier_device_current(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, current; uint16_t power_source; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &power_source); + ret = at_params_unsigned_short_get(param_list, 2, &power_source); if (ret) { return ret; } - ret = at_params_int_get(&slm_at_param_list, 3, ¤t); + ret = at_params_int_get(param_list, 3, ¤t); if (ret) { return ret; } @@ -415,19 +343,21 @@ static int do_carrier_device_current(void) } /* AT#XCARRIER="error","add|remove", */ -static int do_carrier_device_error(void) +SLM_AT_CMD_CUSTOM(xcarrie_error, "AT#XCARRIER=\"error\"", do_carrier_device_error); +static int do_carrier_device_error(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret; int32_t error_code; char operation[7]; int size = sizeof(operation); - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } - ret = at_params_int_get(&slm_at_param_list, 3, &error_code); + ret = at_params_int_get(param_list, 3, &error_code); if (ret) { return ret; } @@ -460,13 +390,15 @@ int lwm2m_carrier_memory_free_read(void) } /* AT#XCARRIER="memory_free","read|write"[,] */ -static int do_carrier_device_mem_free(void) +SLM_AT_CMD_CUSTOM(xcarrier_memory_free, "AT#XCARRIER=\"memory_free\"", do_carrier_device_mem_free); +static int do_carrier_device_mem_free(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, memory; char operation[6]; int size = sizeof(operation); - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } @@ -476,7 +408,7 @@ static int do_carrier_device_mem_free(void) rsp_send("\r\n#XCARRIER: %d\r\n", memory); } else if (slm_util_casecmp(operation, "write")) { - ret = at_params_int_get(&slm_at_param_list, 3, &memory); + ret = at_params_int_get(param_list, 3, &memory); if (ret) { return ret; } @@ -488,11 +420,14 @@ static int do_carrier_device_mem_free(void) } /* AT#XCARRIER="memory_total", */ -static int do_carrier_device_mem_total(void) +SLM_AT_CMD_CUSTOM(xcarrier_memory_total, "AT#XCARRIER=\"memory_total\"", + do_carrier_device_mem_total); +static int do_carrier_device_mem_total(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, memory_total; - ret = at_params_int_get(&slm_at_param_list, 2, &memory_total); + ret = at_params_int_get(param_list, 2, &memory_total); if (ret) { return ret; } @@ -501,20 +436,22 @@ static int do_carrier_device_mem_total(void) } /* AT#XCARRIER="power_sources"[,[[,...[,]]]] */ -static int do_carrier_device_power_sources(void) +SLM_AT_CMD_CUSTOM(xcarrier_power_sources, "AT#XCARRIER=\"power_sources\"", + do_carrier_device_power_sources); +static int do_carrier_device_power_sources(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret; - uint8_t sources[7], count; + uint8_t sources[7]; uint16_t source; - count = at_params_valid_count_get(&slm_at_param_list); - if (count - 2 > sizeof(sources)) { + if (param_count - 2 > sizeof(sources)) { LOG_DBG("AT#XCARRIER=\"power_sources\" failed: too many parameters"); return -EINVAL; } - for (int i = 2; i < count; i++) { - ret = at_params_unsigned_short_get(&slm_at_param_list, i, &source); + for (int i = 2; i < param_count; i++) { + ret = at_params_unsigned_short_get(param_list, i, &source); if (ret) { return ret; } @@ -522,17 +459,19 @@ static int do_carrier_device_power_sources(void) sources[i - 2] = (uint8_t)source; } - return lwm2m_carrier_avail_power_sources_set(sources, count - 2); + return lwm2m_carrier_avail_power_sources_set(sources, param_count - 2); } -/* AT#XCARRIER="timezone","read|write"[,] */ -static int do_carrier_device_timezone(void) +/* AT#XCARRIER="timezone", */ +SLM_AT_CMD_CUSTOM(xcarrier_timezone, "AT#XCARRIER=\"timezone\"", do_carrier_device_timezone); +static int do_carrier_device_timezone(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret; char operation[6]; size_t size = sizeof(operation); - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } @@ -554,7 +493,7 @@ static int do_carrier_device_timezone(void) size = sizeof(timezone); - ret = util_string_get(&slm_at_param_list, 3, timezone, &size); + ret = util_string_get(param_list, 3, timezone, &size); if (ret) { return ret; } @@ -578,7 +517,8 @@ static void print_utc_time(char *output, int32_t timestamp) } /* AT#XCARRIER="time" */ -static int do_carrier_device_time(void) +SLM_AT_CMD_CUSTOM(xcarrier_time, "AT#XCARRIER=\"time\"", do_carrier_device_time); +static int do_carrier_device_time(enum at_cmd_type, const struct at_param_list *, uint32_t) { int utc_time, utc_offset; const char *timezone = NULL; @@ -600,13 +540,16 @@ static int do_carrier_device_time(void) } /* AT#XCARRIER="utc_offset","read|write"[,] */ -static int do_carrier_device_utc_offset(void) +SLM_AT_CMD_CUSTOM(xcarrier_utc_offset, "AT#XCARRIER=\"utc_offset\"", + do_carrier_device_utc_offset); +static int do_carrier_device_utc_offset(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, utc_offset; char operation[6]; size_t size = sizeof(operation); - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } @@ -618,7 +561,7 @@ static int do_carrier_device_utc_offset(void) return 0; } else if (slm_util_casecmp(operation, "WRITE")) { - ret = at_params_int_get(&slm_at_param_list, 3, &utc_offset); + ret = at_params_int_get(param_list, 3, &utc_offset); if (ret) { return ret; } @@ -632,14 +575,16 @@ static int do_carrier_device_utc_offset(void) } /* AT#XCARRIER="utc_time","read|write"[,] */ -static int do_carrier_device_utc_time(void) +SLM_AT_CMD_CUSTOM(xcarrier_utc_time, "AT#XCARRIER=\"utc_time\"", do_carrier_device_utc_time); +static int do_carrier_device_utc_time(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, utc_time; char operation[6]; size_t size = sizeof(operation); char time_str[TIME_STR_SIZE]; - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } @@ -652,7 +597,7 @@ static int do_carrier_device_utc_time(void) return 0; } else if (slm_util_casecmp(operation, "WRITE")) { - ret = at_params_int_get(&slm_at_param_list, 3, &utc_time); + ret = at_params_int_get(param_list, 3, &utc_time); if (ret) { return ret; } @@ -666,17 +611,19 @@ static int do_carrier_device_utc_time(void) } /* AT#XCARRIER="voltage",, */ -static int do_carrier_device_voltage(void) +SLM_AT_CMD_CUSTOM(xcarrier_voltage, "AT#XCARRIER=\"voltage\"", do_carrier_device_voltage); +static int do_carrier_device_voltage(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret, voltage; uint16_t power_source; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &power_source); + ret = at_params_unsigned_short_get(param_list, 2, &power_source); if (ret) { return ret; } - ret = at_params_int_get(&slm_at_param_list, 3, &voltage); + ret = at_params_int_get(param_list, 3, &voltage); if (ret) { return ret; } @@ -685,12 +632,15 @@ static int do_carrier_device_voltage(void) } /* AT#XCARRIER="log_data", */ -static int do_carrier_event_log_log_data(void) +SLM_AT_CMD_CUSTOM(xcarrier_log_data, "AT#XCARRIER=\"log_data\"", + do_carrier_event_log_log_data); +static int do_carrier_event_log_log_data(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t) { char data[CONFIG_SLM_CARRIER_APP_DATA_BUFFER_LEN] = {0}; int size = CONFIG_SLM_CARRIER_APP_DATA_BUFFER_LEN; - int ret = util_string_get(&slm_at_param_list, 2, data, &size); + int ret = util_string_get(param_list, 2, data, &size); if (ret) { return ret; @@ -700,40 +650,42 @@ static int do_carrier_event_log_log_data(void) } /* AT#XCARRIER="position",,,,, */ -static int do_carrier_location_position(void) +SLM_AT_CMD_CUSTOM(xcarrier_position, "AT#XCARRIER=\"position\"", + do_carrier_location_position); +static int do_carrier_location_position(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - int ret, param_count; + int ret; double latitude, longitude; float altitude, uncertainty; uint32_t timestamp; - param_count = at_params_valid_count_get(&slm_at_param_list); if (param_count != 7) { LOG_DBG("AT#XCARRIER=\"position\" failed: invalid number of arguments"); return -EINVAL; } - ret = util_string_to_double_get(&slm_at_param_list, 2, &latitude); + ret = util_string_to_double_get(param_list, 2, &latitude); if (ret) { return ret; } - ret = util_string_to_double_get(&slm_at_param_list, 3, &longitude); + ret = util_string_to_double_get(param_list, 3, &longitude); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 4, &altitude); + ret = util_string_to_float_get(param_list, 4, &altitude); if (ret) { return ret; } - ret = at_params_unsigned_int_get(&slm_at_param_list, 5, ×tamp); + ret = at_params_unsigned_int_get(param_list, 5, ×tamp); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 6, &uncertainty); + ret = util_string_to_float_get(param_list, 6, &uncertainty); if (ret) { return ret; } @@ -742,38 +694,40 @@ static int do_carrier_location_position(void) } /* AT#XCARRIER="velocity",,,,, */ -static int do_carrier_location_velocity(void) +SLM_AT_CMD_CUSTOM(xcarrier_velocity, "AT#XCARRIER=\"velocity\"", + do_carrier_location_velocity); +static int do_carrier_location_velocity(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - int ret, param_count, heading; + int ret, heading; float speed_h, speed_v, uncertainty_h, uncertainty_v; - param_count = at_params_valid_count_get(&slm_at_param_list); if (param_count != 7) { LOG_DBG("AT#XCARRIER=\"velocity\" failed: invalid number of arguments"); return -EINVAL; } - ret = at_params_int_get(&slm_at_param_list, 2, &heading); + ret = at_params_int_get(param_list, 2, &heading); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 3, &speed_h); + ret = util_string_to_float_get(param_list, 3, &speed_h); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 4, &speed_v); + ret = util_string_to_float_get(param_list, 4, &speed_v); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 5, &uncertainty_h); + ret = util_string_to_float_get(param_list, 5, &uncertainty_h); if (ret) { return ret; } - ret = util_string_to_float_get(&slm_at_param_list, 6, &uncertainty_v); + ret = util_string_to_float_get(param_list, 6, &uncertainty_v); if (ret) { return ret; } @@ -781,28 +735,29 @@ static int do_carrier_location_velocity(void) return lwm2m_carrier_velocity_set(heading, speed_h, speed_v, uncertainty_h, uncertainty_v); } -/* AT#XCARRIER="portfolio","create|read|write",[,[,]] */ -static int do_carrier_portfolio(void) +/* AT#XCARRIER="portfolio","create|read|write",[,[,]] */ +SLM_AT_CMD_CUSTOM(xcarrier_portfolio, "AT#XCARRIER=\"portfolio\"", do_carrier_portfolio); +static int do_carrier_portfolio(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - int ret, param_count; + int ret; uint16_t instance_id, identity_type; char operation[7], buffer[64]; size_t size = sizeof(operation); uint16_t buf_len = sizeof(buffer); - ret = util_string_get(&slm_at_param_list, 2, operation, &size); + ret = util_string_get(param_list, 2, operation, &size); if (ret) { return ret; } - ret = at_params_unsigned_short_get(&slm_at_param_list, 3, &instance_id); + ret = at_params_unsigned_short_get(param_list, 3, &instance_id); if (ret) { return ret; } - param_count = at_params_valid_count_get(&slm_at_param_list); if (param_count > 4) { - ret = at_params_unsigned_short_get(&slm_at_param_list, 4, &identity_type); + ret = at_params_unsigned_short_get(param_list, 4, &identity_type); if (ret) { return ret; } @@ -820,7 +775,7 @@ static int do_carrier_portfolio(void) } else if (slm_util_casecmp(operation, "WRITE") && (param_count > 4)) { size = sizeof(buffer); - ret = util_string_get(&slm_at_param_list, 5, buffer, &size); + ret = util_string_get(param_list, 5, buffer, &size); if (ret) { return ret; } @@ -836,48 +791,52 @@ static int do_carrier_portfolio(void) } /* AT#XCARRIER="reboot" */ -static int do_carrier_request_reboot(void) +SLM_AT_CMD_CUSTOM(xcarrier_reboot, "AT#XCARRIER=\"reboot\"", do_carrier_request_reboot); +static int do_carrier_request_reboot(enum at_cmd_type, const struct at_param_list *, uint32_t) { return lwm2m_carrier_request(LWM2M_CARRIER_REQUEST_REBOOT); } /* AT#XCARRIER="link_down" */ -static int do_carrier_request_link_down(void) +SLM_AT_CMD_CUSTOM(xcarrier_link_down, "AT#XCARRIER=\"link_down\"", + do_carrier_request_link_down); +static int do_carrier_request_link_down(enum at_cmd_type, const struct at_param_list *, uint32_t) { return lwm2m_carrier_request(LWM2M_CARRIER_REQUEST_LINK_DOWN); } /* AT#XCARRIER="link_up" */ -static int do_carrier_request_link_up(void) +SLM_AT_CMD_CUSTOM(xcarrier_link_up, "AT#XCARRIER=\"link_up\"", do_carrier_request_link_up); +static int do_carrier_request_link_up(enum at_cmd_type, const struct at_param_list *, uint32_t) { return lwm2m_carrier_request(LWM2M_CARRIER_REQUEST_LINK_UP); } -/** - * @brief API to handle AT#XCARRIER command. - */ -int handle_at_carrier(enum at_cmd_type cmd_type) +/* AT#XCARRIER="send",,,[,] */ +SLM_AT_CMD_CUSTOM(xcarrier_send, "AT#XCARRIER=\"send\"", do_carrier_send); +static int do_carrier_send(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - int ret; - char op_str[SLM_CARRIER_OP_STR_MAX]; - int size = sizeof(op_str); + int ret = 0; - if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { + if (param_count != 5 && param_count != 6) { + LOG_DBG("AT#XCARRIER=\"send\" failed: invalid number of arguments"); return -EINVAL; } - ret = util_string_get(&slm_at_param_list, 1, op_str, &size); - if (ret) { - return ret; - } - ret = -EINVAL; - for (int i = 0; i < CARRIER_OP_MAX; i++) { - if (slm_util_casecmp(op_str, op_list[i].op_str)) { - ret = op_list[i].handler(); - break; + + uint16_t path[4]; + uint8_t path_len = 0; + + for (int i = 2; i < param_count; i++) { + ret = at_params_unsigned_short_get(param_list, i, &path[i - 2]); + if (ret) { + return ret; } + + ++path_len; } - return ret; + return lwm2m_carrier_data_send(path, path_len); } int slm_at_carrier_init(void) diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.h b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.h index d6fe5e3b2da..52b3255f1cc 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.h +++ b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.h @@ -31,11 +31,6 @@ int slm_at_carrier_init(void); */ int slm_at_carrier_uninit(void); -/** - * @brief AT#XCARRIER command handler. - */ -int handle_at_carrier(enum at_cmd_type cmd_type); - /** @} */ #endif /* SLM_AT_CARRIER_ */ diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c index 09ffe3b6f60..8b582f8c800 100644 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c +++ b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.c @@ -14,145 +14,22 @@ LOG_MODULE_REGISTER(slm_carrier_cfg, CONFIG_SLM_LOG_LEVEL); -/**@brief LwM2M Carrier Configuration operations. */ -enum slm_carrier_cfg_operation { - /* Enable Automatic Startup */ - CARRIER_CFG_OP_AUTO_STARTUP, - /* General Custom Configuration */ - CARRIER_CFG_OP_CONFIG_ENABLE, - CARRIER_CFG_OP_CONFIG_APN, - CARRIER_CFG_OP_CONFIG_BOOTSTRAP_FROM_SMARTCARD, - CARRIER_CFG_OP_CONFIG_CARRIERS, - CARRIER_CFG_OP_CONFIG_COAP_CON_INTERVAL, - CARRIER_CFG_OP_CONFIG_LGU_DEVICE_SERIAL_NO_TYPE, - CARRIER_CFG_OP_CONFIG_LGU_SERVICE_CODE, - CARRIER_CFG_OP_CONFIG_PDN_TYPE, - CARRIER_CFG_OP_CONFIG_SESSION_IDLE_TIMEOUT, - /* Device Custom Configuration */ - CARRIER_CFG_OP_DEVICE_ENABLE, - CARRIER_CFG_OP_DEVICE_DEVICE_TYPE, - CARRIER_CFG_OP_DEVICE_HW_VERSION, - CARRIER_CFG_OP_DEVICE_MANUFACTURER, - CARRIER_CFG_OP_DEVICE_MODEL_NUMBER, - CARRIER_CFG_OP_DEVICE_SW_VERSION, - /* Server Custom Configuration */ - CARRIER_CFG_OP_SERVER_ENABLE, - CARRIER_CFG_OP_SERVER_BINDING, - CARRIER_CFG_OP_SERVER_IS_BOOTSTRAP, - CARRIER_CFG_OP_SERVER_LIFETIME, - CARRIER_CFG_OP_SERVER_SEC_TAG, - CARRIER_CFG_OP_SERVER_URI, - /* Count */ - CARRIER_CFG_OP_MAX -}; - -/** forward declaration of configuration cmd handlers **/ -static int do_cfg_apn(void); -static int do_cfg_auto_startup(void); -static int do_cfg_bootstrap_from_smartcard(void); -static int do_cfg_carriers(void); -static int do_cfg_coap_con_interval(void); -static int do_cfg_config_enable(void); -static int do_cfg_device_enable(void); -static int do_cfg_device_type(void); -static int do_cfg_hardware_version(void); -static int do_cfg_manufacturer(void); -static int do_cfg_model_number(void); -static int do_cfg_session_idle_timeout(void); -static int do_cfg_software_version(void); -static int do_cfg_device_serial_no_type(void); -static int do_cfg_service_code(void); -static int do_cfg_pdn_type(void); -static int do_cfg_binding(void); -static int do_cfg_server_enable(void); -static int do_cfg_is_bootstrap(void); -static int do_cfg_lifetime(void); -static int do_cfg_sec_tag(void); -static int do_cfg_uri(void); - -struct carrier_cfg_op_list { - uint8_t op_code; - char *op_str; - int (*handler)(void); -}; - -/**@brief SLM Carrier Configuration AT Command list type. */ -static struct carrier_cfg_op_list cfg_op_list[CARRIER_CFG_OP_MAX] = { - {CARRIER_CFG_OP_AUTO_STARTUP, "auto_startup", do_cfg_auto_startup}, - {CARRIER_CFG_OP_CONFIG_APN, "apn", do_cfg_apn}, - {CARRIER_CFG_OP_CONFIG_BOOTSTRAP_FROM_SMARTCARD, "bootstrap_smartcard", - do_cfg_bootstrap_from_smartcard}, - {CARRIER_CFG_OP_CONFIG_CARRIERS, "carriers", do_cfg_carriers}, - {CARRIER_CFG_OP_CONFIG_COAP_CON_INTERVAL, "coap_con_interval", do_cfg_coap_con_interval}, - {CARRIER_CFG_OP_CONFIG_ENABLE, "config_enable", do_cfg_config_enable}, - {CARRIER_CFG_OP_CONFIG_LGU_DEVICE_SERIAL_NO_TYPE, "device_serial_no_type", - do_cfg_device_serial_no_type}, - {CARRIER_CFG_OP_CONFIG_LGU_SERVICE_CODE, "service_code", do_cfg_service_code}, - {CARRIER_CFG_OP_CONFIG_PDN_TYPE, "pdn_type", do_cfg_pdn_type}, - {CARRIER_CFG_OP_CONFIG_SESSION_IDLE_TIMEOUT, "session_idle_timeout", - do_cfg_session_idle_timeout}, - {CARRIER_CFG_OP_DEVICE_ENABLE, "device_enable", do_cfg_device_enable}, - {CARRIER_CFG_OP_DEVICE_DEVICE_TYPE, "device_type", do_cfg_device_type}, - {CARRIER_CFG_OP_DEVICE_HW_VERSION, "hardware_version", do_cfg_hardware_version}, - {CARRIER_CFG_OP_DEVICE_MANUFACTURER, "manufacturer", do_cfg_manufacturer}, - {CARRIER_CFG_OP_DEVICE_MODEL_NUMBER, "model_number", do_cfg_model_number}, - {CARRIER_CFG_OP_DEVICE_SW_VERSION, "software_version", do_cfg_software_version}, - {CARRIER_CFG_OP_SERVER_BINDING, "binding", do_cfg_binding}, - {CARRIER_CFG_OP_SERVER_ENABLE, "server_enable", do_cfg_server_enable}, - {CARRIER_CFG_OP_SERVER_IS_BOOTSTRAP, "is_bootstrap", do_cfg_is_bootstrap}, - {CARRIER_CFG_OP_SERVER_LIFETIME, "lifetime", do_cfg_lifetime}, - {CARRIER_CFG_OP_SERVER_SEC_TAG, "sec_tag", do_cfg_sec_tag}, - {CARRIER_CFG_OP_SERVER_URI, "uri", do_cfg_uri}, -}; - -#define SLM_CARRIER_CFG_OP_STR_MAX (sizeof("device_serial_no_type") + 1) - -/** - * @brief API to handle AT#XCARRIERCFG command. - */ -int handle_at_carrier_cfg(enum at_cmd_type cmd_type) -{ - int ret; - char op_str[SLM_CARRIER_CFG_OP_STR_MAX]; - int size = sizeof(op_str); - - if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { - return -EINVAL; - } - - ret = util_string_get(&slm_at_param_list, 1, op_str, &size); - if (ret) { - return ret; - } - - ret = -EINVAL; - for (int i = 0; i < CARRIER_CFG_OP_MAX; i++) { - if (slm_util_casecmp(op_str, cfg_op_list[i].op_str)) { - ret = cfg_op_list[i].handler(); - break; - } - } - - return ret; -} - /* AT#XCARRIERCFG="apn"[,] */ -static int do_cfg_apn(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_apn, "AT#XCARRIERCFG=\"apn\"", do_cfg_apn); +static int do_cfg_apn(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_apn_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } char apn[64]; int ret, size = sizeof(apn); - ret = util_string_get(&slm_at_param_list, 2, apn, &size); + ret = util_string_get(param_list, 2, apn, &size); if (ret) { return ret; } @@ -161,22 +38,21 @@ static int do_cfg_apn(void) } /* AT#XCARRIERCFG="auto_startup"[,<0|1>] */ -static int do_cfg_auto_startup(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_auto_startup, "AT#XCARRIERCFG=\"auto_startup\"", do_cfg_auto_startup); +static int do_cfg_auto_startup(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_auto_startup_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t auto_startup; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &auto_startup); + ret = at_params_unsigned_short_get(param_list, 2, &auto_startup); if (ret) { return ret; } @@ -190,22 +66,22 @@ static int do_cfg_auto_startup(void) } /* AT#XCARRIERCFG="bootstrap_smartcard"[,<0|1>] */ -static int do_cfg_bootstrap_from_smartcard(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_bootstrap_smartcard, "AT#XCARRIERCFG=\"bootstrap_smartcard\"", + do_cfg_bootstrap_from_smartcard); +static int do_cfg_bootstrap_from_smartcard(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_bootstrap_from_smartcard_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t enabled; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &enabled); + ret = at_params_unsigned_short_get(param_list, 2, &enabled); if (ret) { return ret; } @@ -221,7 +97,7 @@ static int do_cfg_bootstrap_from_smartcard(void) const static uint32_t carriers_enabled_map[] = { LWM2M_CARRIER_GENERIC, LWM2M_CARRIER_VERIZON, - LWM2M_CARRIER_ATT, + LWM2M_CARRIER_BELL_CA, LWM2M_CARRIER_LG_UPLUS, LWM2M_CARRIER_T_MOBILE, LWM2M_CARRIER_SOFTBANK @@ -250,31 +126,30 @@ static const char *carriers_enabled_str(void) } /* AT#XCARRIERCFG="carriers"[,"all"|[[,...[,]]]] */ -static int do_cfg_carriers(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_carriers, "AT#XCARRIERCFG=\"carriers\"", do_cfg_carriers); +static int do_cfg_carriers(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", carriers_enabled_str()); return 0; - } else if (count - 2 > ARRAY_SIZE(carriers_enabled_map)) { + } else if (param_count - 2 > ARRAY_SIZE(carriers_enabled_map)) { LOG_ERR("AT#XCARRIERCFG=\"carriers\" failed: too many parameters"); return -EINVAL; } uint32_t carriers_enabled = 0; int ret, size = sizeof("all"); - char buf[size]; + char size_buf[size]; - ret = util_string_get(&slm_at_param_list, 2, buf, &size); - if (!ret && slm_util_casecmp(buf, "all")) { + ret = util_string_get(param_list, 2, size_buf, &size); + if (!ret && slm_util_casecmp(size_buf, "all")) { carriers_enabled = UINT32_MAX; } else { - for (int i = 2; i < count; i++) { + for (int i = 2; i < param_count; i++) { uint16_t carrier; - ret = at_params_unsigned_short_get(&slm_at_param_list, i, &carrier); + ret = at_params_unsigned_short_get(param_list, i, &carrier); if (ret || (carrier >= ARRAY_SIZE(carriers_enabled_map))) { LOG_ERR("AT#XCARRIERCFG=\"carriers\" failed: illegal operator"); return -EINVAL; @@ -288,21 +163,21 @@ static int do_cfg_carriers(void) } /* AT#XCARRIERCFG="coap_con_interval"[,] */ -static int do_cfg_coap_con_interval(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_coap_con_interval, "AT#XCARRIERCFG=\"coap_con_interval\"", + do_cfg_coap_con_interval); +static int do_cfg_coap_con_interval(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_coap_con_interval_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret, coap_con_interval; - ret = at_params_int_get(&slm_at_param_list, 2, &coap_con_interval); + ret = at_params_int_get(param_list, 2, &coap_con_interval); if (ret) { return ret; } @@ -316,23 +191,49 @@ static int do_cfg_coap_con_interval(void) return lwm2m_settings_coap_con_interval_set(coap_con_interval); } -/* AT#XCARRIERCFG="config_enable"[,<0|1>] */ -static int do_cfg_config_enable(void) +/* AT#XCARRIERCFG="download_timeout"[,] */ +SLM_AT_CMD_CUSTOM(xcarriercfg_download_timeout, "AT#XCARRIERCFG=\"download_timeout\"", + do_cfg_firmware_download_timeout); +static int do_cfg_firmware_download_timeout(enum at_cmd_type, + const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; + if (param_count == 2) { + rsp_send("\r\n#XCARRIERCFG: %hu\r\n", + lwm2m_settings_firmware_download_timeout_get()); + return 0; + } else if (param_count != 3) { + return -EINVAL; + } + + int ret; + uint16_t firmware_download_timeout; + + ret = at_params_unsigned_short_get(param_list, 2, &firmware_download_timeout); + if (ret) { + return ret; + } + + return lwm2m_settings_firmware_download_timeout_set(firmware_download_timeout); +} - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { +/* AT#XCARRIERCFG="config_enable"[,<0|1>] */ +SLM_AT_CMD_CUSTOM(xcarriercfg_config_enable, "AT#XCARRIERCFG=\"config_enable\"", + do_cfg_config_enable); +static int do_cfg_config_enable(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) +{ + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_enable_custom_config_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t enabled; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &enabled); + ret = at_params_unsigned_short_get(param_list, 2, &enabled); if (ret) { return ret; } @@ -346,23 +247,23 @@ static int do_cfg_config_enable(void) } /* AT#XCARRIERCFG="device_enable"[,<0|1>] */ -static int do_cfg_device_enable(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_device_enable, "AT#XCARRIERCFG=\"device_enable\"", + do_cfg_device_enable); +static int do_cfg_device_enable(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_enable_custom_device_config_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t enabled; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &enabled); + ret = at_params_unsigned_short_get(param_list, 2, &enabled); if (ret) { return ret; } @@ -376,15 +277,14 @@ static int do_cfg_device_enable(void) } /* AT#XCARRIERCFG="device_type"[,] */ -static int do_cfg_device_type(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_device_type, "AT#XCARRIERCFG=\"device_type\"", do_cfg_device_type); +static int do_cfg_device_type(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_device_type_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -392,7 +292,7 @@ static int do_cfg_device_type(void) char device_type[32]; int size = sizeof(device_type); - ret = util_string_get(&slm_at_param_list, 2, device_type, &size); + ret = util_string_get(param_list, 2, device_type, &size); if (ret) { return ret; } @@ -401,15 +301,15 @@ static int do_cfg_device_type(void) } /* AT#XCARRIERCFG="hardware_version"[,] */ -static int do_cfg_hardware_version(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_hardware_version, "AT#XCARRIERCFG=\"hardware_version\"", + do_cfg_hardware_version); +static int do_cfg_hardware_version(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_hardware_version_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -417,7 +317,7 @@ static int do_cfg_hardware_version(void) char hardware_version[32]; int size = sizeof(hardware_version); - ret = util_string_get(&slm_at_param_list, 2, hardware_version, &size); + ret = util_string_get(param_list, 2, hardware_version, &size); if (ret) { return ret; } @@ -426,15 +326,14 @@ static int do_cfg_hardware_version(void) } /* AT#XCARRIERCFG="manufacturer"[,] */ -static int do_cfg_manufacturer(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_manufacturer, "AT#XCARRIERCFG=\"manufacturer\"", do_cfg_manufacturer); +static int do_cfg_manufacturer(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_manufacturer_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -442,7 +341,7 @@ static int do_cfg_manufacturer(void) char manufacturer[32]; int size = sizeof(manufacturer); - ret = util_string_get(&slm_at_param_list, 2, manufacturer, &size); + ret = util_string_get(param_list, 2, manufacturer, &size); if (ret) { return ret; } @@ -451,15 +350,14 @@ static int do_cfg_manufacturer(void) } /* AT#XCARRIERCFG="model_number"[,] */ -static int do_cfg_model_number(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_model_number, "AT#XCARRIERCFG=\"model_number\"", do_cfg_model_number); +static int do_cfg_model_number(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_model_number_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -467,7 +365,7 @@ static int do_cfg_model_number(void) char model_number[32]; int size = sizeof(model_number); - ret = util_string_get(&slm_at_param_list, 2, model_number, &size); + ret = util_string_get(param_list, 2, model_number, &size); if (ret) { return ret; } @@ -476,15 +374,15 @@ static int do_cfg_model_number(void) } /* AT#XCARRIERCFG="software_version"[,] */ -static int do_cfg_software_version(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_software_version, "AT#XCARRIERCFG=\"software_version\"", + do_cfg_software_version); +static int do_cfg_software_version(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_software_version_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -492,7 +390,7 @@ static int do_cfg_software_version(void) char software_version[32]; int size = sizeof(software_version); - ret = util_string_get(&slm_at_param_list, 2, software_version, &size); + ret = util_string_get(param_list, 2, software_version, &size); if (ret) { return ret; } @@ -501,21 +399,21 @@ static int do_cfg_software_version(void) } /* AT#XCARRIERCFG="session_idle_timeout"[,] */ -static int do_cfg_session_idle_timeout(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_session_idle_timeout, "AT#XCARRIERCFG=\"session_idle_timeout\"", + do_cfg_session_idle_timeout); +static int do_cfg_session_idle_timeout(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_session_idle_timeout_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret, session_idle_timeout; - ret = at_params_int_get(&slm_at_param_list, 2, &session_idle_timeout); + ret = at_params_int_get(param_list, 2, &session_idle_timeout); if (ret) { return ret; } @@ -530,21 +428,21 @@ static int do_cfg_session_idle_timeout(void) } /* AT#XCARRIERCFG="device_serial_no_type"[,<0|1>] */ -static int do_cfg_device_serial_no_type(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_device_serial_no_type, "AT#XCARRIERCFG=\"device_serial_no_type\"", + do_cfg_device_serial_no_type); +static int do_cfg_device_serial_no_type(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_device_serial_no_type_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret, serial_no_type; - ret = at_params_int_get(&slm_at_param_list, 2, &serial_no_type); + ret = at_params_int_get(param_list, 2, &serial_no_type); if (ret) { return ret; } @@ -565,15 +463,14 @@ static int do_cfg_device_serial_no_type(void) } /* AT#XCARRIERCFG="service_code"[,] */ -static int do_cfg_service_code(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_service_code, "AT#XCARRIERCFG=\"service_code\"", do_cfg_service_code); +static int do_cfg_service_code(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_service_code_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -581,7 +478,7 @@ static int do_cfg_service_code(void) char service_code[5]; int size = sizeof(service_code); - ret = util_string_get(&slm_at_param_list, 2, service_code, &size); + ret = util_string_get(param_list, 2, service_code, &size); if (ret) { return ret; } @@ -590,22 +487,21 @@ static int do_cfg_service_code(void) } /* AT#XCARRIERCFG="pdn_type"[,] */ -static int do_cfg_pdn_type(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_pdn_type, "AT#XCARRIERCFG=\"pdn_type\"", do_cfg_pdn_type); +static int do_cfg_pdn_type(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_pdn_type_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t pdn_type; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &pdn_type); + ret = at_params_unsigned_short_get(param_list, 2, &pdn_type); if (ret) { return ret; } @@ -631,16 +527,43 @@ static int do_cfg_pdn_type(void) return lwm2m_settings_pdn_type_set(pdn_type); } -/* AT#XCARRIERCFG="binding"[,] */ -static int do_cfg_binding(void) +/* AT#XCARRIERCFG="queue_mode"[,<0|1>] */ +SLM_AT_CMD_CUSTOM(xcarriercfg_queue_mode, "AT#XCARRIERCFG=\"queue_mode\"", do_cfg_queue_mode); +static int do_cfg_queue_mode(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; + if (param_count == 2) { + rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_queue_mode_get()); + return 0; + } else if (param_count != 3) { + return -EINVAL; + } - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + int ret; + uint16_t queue_mode; + + ret = at_params_unsigned_short_get(param_list, 2, &queue_mode); + if (ret) { + return ret; + } + + if (queue_mode > 1) { + LOG_ERR("AT#XCARRIERCFG=\"queue_mode\" failed: must be 0 or 1"); + return -EINVAL; + } + + return lwm2m_settings_queue_mode_set(queue_mode); +} + +/* AT#XCARRIERCFG="binding"[,] */ +SLM_AT_CMD_CUSTOM(xcarriercfg_binding, "AT#XCARRIERCFG=\"binding\"", do_cfg_binding); +static int do_cfg_binding(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) +{ + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %c\r\n", lwm2m_settings_server_binding_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -648,7 +571,7 @@ static int do_cfg_binding(void) int size = sizeof("U"); char binding[size]; - ret = util_string_get(&slm_at_param_list, 2, binding, &size); + ret = util_string_get(param_list, 2, binding, &size); if (ret) { return ret; } @@ -662,23 +585,23 @@ static int do_cfg_binding(void) } /* AT#XCARRIERCFG="server_enable"[,<0|1>] */ -static int do_cfg_server_enable(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_server_enable, "AT#XCARRIERCFG=\"server_enable\"", + do_cfg_server_enable); +static int do_cfg_server_enable(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_enable_custom_server_config_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t enabled; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &enabled); + ret = at_params_unsigned_short_get(param_list, 2, &enabled); if (ret) { return ret; } @@ -692,22 +615,21 @@ static int do_cfg_server_enable(void) } /* AT#XCARRIERCFG="is_bootstrap"[,<0|1>] */ -static int do_cfg_is_bootstrap(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_is_bootstrap, "AT#XCARRIERCFG=\"is_bootstrap\"", do_cfg_is_bootstrap); +static int do_cfg_is_bootstrap(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_is_bootstrap_server_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint16_t is_bootstrap; - ret = at_params_unsigned_short_get(&slm_at_param_list, 2, &is_bootstrap); + ret = at_params_unsigned_short_get(param_list, 2, &is_bootstrap); if (ret) { return ret; } @@ -721,21 +643,20 @@ static int do_cfg_is_bootstrap(void) } /* AT#XCARRIERCFG="lifetime"[,] */ -static int do_cfg_lifetime(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_lifetime, "AT#XCARRIERCFG=\"lifetime\"", do_cfg_lifetime); +static int do_cfg_lifetime(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %d\r\n", lwm2m_settings_server_lifetime_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret, lifetime; - ret = at_params_int_get(&slm_at_param_list, 2, &lifetime); + ret = at_params_int_get(param_list, 2, &lifetime); if (ret) { return ret; } @@ -750,22 +671,21 @@ static int do_cfg_lifetime(void) } /* AT#XCARRIERCFG="sec_tag"[,] */ -static int do_cfg_sec_tag(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_sec_tag, "AT#XCARRIERCFG=\"sec_tag\"", do_cfg_sec_tag); +static int do_cfg_sec_tag(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %u\r\n", lwm2m_settings_server_sec_tag_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } int ret; uint32_t sec_tag; - ret = at_params_unsigned_int_get(&slm_at_param_list, 2, &sec_tag); + ret = at_params_unsigned_int_get(param_list, 2, &sec_tag); if (ret) { return ret; } @@ -774,15 +694,14 @@ static int do_cfg_sec_tag(void) } /* AT#XCARRIERCFG="uri"[,] */ -static int do_cfg_uri(void) +SLM_AT_CMD_CUSTOM(xcarriercfg_uri, "AT#XCARRIERCFG=\"uri\"", do_cfg_uri); +static int do_cfg_uri(enum at_cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { - uint32_t count; - - count = at_params_valid_count_get(&slm_at_param_list); - if (count == 2) { + if (param_count == 2) { rsp_send("\r\n#XCARRIERCFG: %s\r\n", lwm2m_settings_server_uri_get()); return 0; - } else if (count != 3) { + } else if (param_count != 3) { return -EINVAL; } @@ -790,7 +709,7 @@ static int do_cfg_uri(void) char server_uri[255]; int size = sizeof(server_uri); - ret = util_string_get(&slm_at_param_list, 2, server_uri, &size); + ret = util_string_get(param_list, 2, server_uri, &size); if (ret) { return ret; } diff --git a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.h b/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.h deleted file mode 100644 index bca70e7ffc1..00000000000 --- a/applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier_cfg.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef SLM_AT_CARRIER_CFG_ -#define SLM_AT_CARRIER_CFG_ - -#include - -/**@file slm_at_carrier_cfg.h - * - * @brief Custom AT command to configure the LwM2M Carrier library. - * @{ - */ -/** - * @brief AT#XCARRIERCFG command handler. - */ -int handle_at_carrier_cfg(enum at_cmd_type cmd_type); - -/** @} */ - -#endif /* SLM_AT_CARRIER_CFG_ */ diff --git a/applications/serial_lte_modem/src/main.c b/applications/serial_lte_modem/src/main.c index 2c0d7875158..20609008089 100644 --- a/applications/serial_lte_modem/src/main.c +++ b/applications/serial_lte_modem/src/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,6 @@ #include "slm_at_host.h" #include "slm_at_fota.h" #include "slm_settings.h" -#include "slm_uart_handler.h" #include "slm_util.h" LOG_MODULE_REGISTER(slm, CONFIG_SLM_LOG_LEVEL); @@ -35,8 +35,12 @@ LOG_MODULE_REGISTER(slm, CONFIG_SLM_LOG_LEVEL); static K_THREAD_STACK_DEFINE(slm_wq_stack_area, SLM_WQ_STACK_SIZE); static const struct device *gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)); +#if POWER_PIN_IS_ENABLED static struct gpio_callback gpio_cb; -static atomic_t gpio_cb_running; /* Protect the gpio_cb. */ +#else +BUILD_ASSERT(!IS_ENABLED(CONFIG_SLM_START_SLEEP), + "CONFIG_SLM_START_SLEEP requires CONFIG_SLM_POWER_PIN to be defined."); +#endif static struct k_work_delayable indicate_work; struct k_work_q slm_work_q; @@ -44,8 +48,6 @@ struct k_work_q slm_work_q; /* Forward declarations */ static void indicate_wk(struct k_work *work); -BUILD_ASSERT(CONFIG_SLM_WAKEUP_PIN >= 0, "Wake up pin not configured"); - NRF_MODEM_LIB_ON_INIT(lwm2m_init_hook, on_modem_lib_init, NULL); NRF_MODEM_LIB_ON_DFU_RES(main_dfu_hook, on_modem_dfu_res, NULL); @@ -125,38 +127,95 @@ static int ext_xtal_control(bool xtal_on) return err; } -/* This function is safe to call twice after reset */ -static int init_gpio(void) +#if POWER_PIN_IS_ENABLED + +static int configure_power_pin_interrupt(gpio_callback_handler_t handler, gpio_flags_t flags) { int err; + const gpio_pin_t pin = CONFIG_SLM_POWER_PIN; - if (!device_is_ready(gpio_dev)) { - LOG_ERR("GPIO controller not ready"); - return -ENODEV; + /* First disable the previously configured interrupt. Somehow when in idle mode if + * the wake-up interrupt is configured to be on an edge the power consumption + * drastically increases (3x), which is is why it is configured to be level-triggered. + * When entering idle for some reason first disabling the previously edge-level + * configured interrupt is also needed to keep the power consumption down. + */ + gpio_pin_interrupt_configure(gpio_dev, pin, GPIO_INT_DISABLE); + + err = gpio_pin_interrupt_configure(gpio_dev, pin, flags); + if (err) { + LOG_ERR("Failed to configure %s (0x%x) on power pin. (%d)", + "interrupt", flags, err); + return err; } - err = gpio_pin_configure(gpio_dev, CONFIG_SLM_WAKEUP_PIN, - GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_LOW); + + gpio_init_callback(&gpio_cb, handler, BIT(pin)); + + err = gpio_add_callback(gpio_dev, &gpio_cb); if (err) { - LOG_ERR("GPIO_0 config error: %d", err); + LOG_ERR("Failed to configure %s (0x%x) on power pin. (%d)", "callback", flags, err); return err; } -#if (CONFIG_SLM_INDICATE_PIN >= 0) - err = gpio_pin_configure(gpio_dev, CONFIG_SLM_INDICATE_PIN, - GPIO_OUTPUT_INACTIVE | GPIO_ACTIVE_LOW); + + LOG_DBG("Configured interrupt (0x%x) on power pin (%u).", flags, pin); + return 0; +} + +static void power_pin_callback_poweroff(const struct device *, struct gpio_callback *, uint32_t) +{ + LOG_INF("Power off triggered."); + slm_enter_sleep(); +} + +static void poweroff_interrupt_enabler(struct k_work *) +{ + configure_power_pin_interrupt(power_pin_callback_poweroff, GPIO_INT_EDGE_RISING); +} + +#endif /* POWER_PIN_IS_ENABLED */ + +#if POWER_PIN_IS_ENABLED || INDICATE_PIN_IS_ENABLED + +static int configure_gpio(gpio_pin_t pin, gpio_flags_t flags) +{ + const int err = gpio_pin_configure(gpio_dev, pin, flags); + if (err) { - LOG_ERR("GPIO_0 config error: %d", err); + LOG_ERR("Failed to configure GPIO pin P0.%d. (%d)", pin, err); return err; } + + return 0; +} +#endif + +static int init_gpios(void) +{ + if (!device_is_ready(gpio_dev)) { + LOG_ERR("GPIO controller not ready"); + return -ENODEV; + } + +#if POWER_PIN_IS_ENABLED + if (configure_gpio(CONFIG_SLM_POWER_PIN, GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_LOW)) { + return -1; + } +#endif + +#if INDICATE_PIN_IS_ENABLED + if (configure_gpio(CONFIG_SLM_INDICATE_PIN, GPIO_OUTPUT_INACTIVE | GPIO_ACTIVE_LOW)) { + return -1; + } #endif return 0; } -int indicate_start(void) +int slm_indicate(void) { int err = 0; -#if (CONFIG_SLM_INDICATE_PIN >= 0) +#if (INDICATE_PIN_IS_ENABLED) if (k_work_delayable_is_pending(&indicate_work)) { return 0; } @@ -173,7 +232,7 @@ int indicate_start(void) static void indicate_stop(void) { -#if (CONFIG_SLM_INDICATE_PIN >= 0) +#if (INDICATE_PIN_IS_ENABLED) if (gpio_pin_set(gpio_dev, CONFIG_SLM_INDICATE_PIN, 0) != 0) { LOG_WRN("GPIO_0 set error"); } @@ -181,23 +240,36 @@ static void indicate_stop(void) #endif } -static void gpio_cb_func(const struct device *dev, struct gpio_callback *gpio_callback, - uint32_t pins) +#if POWER_PIN_IS_ENABLED + +static void power_pin_callback_enable_poweroff(const struct device *dev, + struct gpio_callback *gpio_callback, uint32_t) { - int err; + static K_WORK_DELAYABLE_DEFINE(work, poweroff_interrupt_enabler); - if ((BIT(CONFIG_SLM_WAKEUP_PIN) & pins) == 0) { - return; - } + LOG_DBG("Enabling the poweroff interrupt shortly..."); + gpio_remove_callback(dev, gpio_callback); + + /* Enable the poweroff interrupt after a small delay + * so that it doesn't fire right away (which it does if enabled here). + */ + k_work_schedule(&work, K_MSEC(1)); +} + +static void power_pin_callback_wakeup(const struct device *dev, + struct gpio_callback *gpio_callback, uint32_t) +{ + static atomic_t callback_running; + int err; /* Prevent level triggered interrupt running this multiple times. */ - if (!atomic_cas(&gpio_cb_running, false, true)) { + if (!atomic_cas(&callback_running, false, true)) { return; } - LOG_INF("Exit idle"); + LOG_INF("Resuming from idle."); if (k_work_delayable_is_pending(&indicate_work)) { - (void)k_work_cancel_delayable(&indicate_work); + k_work_cancel_delayable(&indicate_work); indicate_stop(); } @@ -205,31 +277,30 @@ static void gpio_cb_func(const struct device *dev, struct gpio_callback *gpio_ca if (err < 0) { LOG_WRN("Failed to enable ext XTAL: %d", err); } - err = slm_uart_power_on(); + err = slm_at_host_power_on(); if (err) { - (void)atomic_set(&gpio_cb_running, false); + atomic_set(&callback_running, false); LOG_ERR("Failed to power on uart: %d", err); return; } - gpio_pin_interrupt_configure(gpio_dev, CONFIG_SLM_WAKEUP_PIN, GPIO_INT_DISABLE); - gpio_remove_callback(gpio_dev, gpio_callback); - (void)atomic_set(&gpio_cb_running, false); + gpio_remove_callback(dev, gpio_callback); + + /* Enable the poweroff interrupt only when the pin will be back to a nonactive state. */ + configure_power_pin_interrupt(power_pin_callback_enable_poweroff, GPIO_INT_EDGE_RISING); + + atomic_set(&callback_running, false); } -void enter_idle(void) +void slm_enter_idle(void) { + LOG_INF("Entering idle."); int err; - gpio_init_callback(&gpio_cb, gpio_cb_func, BIT(CONFIG_SLM_WAKEUP_PIN)); - err = gpio_add_callback(gpio_dev, &gpio_cb); - if (err) { - LOG_ERR("GPIO_0 add callback error: %d", err); - return; - } - err = gpio_pin_interrupt_configure(gpio_dev, CONFIG_SLM_WAKEUP_PIN, GPIO_INT_LEVEL_LOW); + gpio_remove_callback(gpio_dev, &gpio_cb); + + err = configure_power_pin_interrupt(power_pin_callback_wakeup, GPIO_INT_LEVEL_LOW); if (err) { - LOG_ERR("GPIO_0 enable callback error: %d", err); return; } @@ -239,29 +310,50 @@ void enter_idle(void) } } -void enter_sleep(void) +FUNC_NORETURN static void enter_sleep_no_uninit(void) { - /* - * Due to errata 4, Always configure PIN_CNF[n].INPUT before PIN_CNF[n].SENSE. - * At this moment WAKEUP_PIN has already been configured as INPUT at init_gpio(). - */ - nrf_gpio_cfg_sense_set(CONFIG_SLM_WAKEUP_PIN, NRF_GPIO_PIN_SENSE_LOW); + LOG_INF("Entering sleep."); + LOG_PANIC(); + nrf_gpio_cfg_sense_set(CONFIG_SLM_POWER_PIN, NRF_GPIO_PIN_SENSE_LOW); k_sleep(K_MSEC(100)); nrf_regulators_system_off(NRF_REGULATORS_NS); + assert(false); +} + +FUNC_NORETURN void slm_enter_sleep(void) +{ + slm_at_host_uninit(); + + /* Only power off the modem if it has not been put + * in flight mode to allow reducing NVM wear. + */ + if (!slm_is_modem_functional_mode(LTE_LC_FUNC_MODE_OFFLINE)) { + slm_power_off_modem(); + } + enter_sleep_no_uninit(); } -void enter_shutdown(void) +#endif /* POWER_PIN_IS_ENABLED */ + +FUNC_NORETURN void slm_enter_shutdown(void) { + LOG_INF("Entering shutdown."); + /* De-configure GPIOs */ - gpio_pin_interrupt_configure(gpio_dev, CONFIG_SLM_WAKEUP_PIN, GPIO_INT_DISABLE); - gpio_pin_configure(gpio_dev, CONFIG_SLM_WAKEUP_PIN, GPIO_DISCONNECTED); +#if POWER_PIN_IS_ENABLED + gpio_pin_interrupt_configure(gpio_dev, CONFIG_SLM_POWER_PIN, GPIO_INT_DISABLE); + gpio_pin_configure(gpio_dev, CONFIG_SLM_POWER_PIN, GPIO_DISCONNECTED); +#endif +#if INDICATE_PIN_IS_ENABLED gpio_pin_configure(gpio_dev, CONFIG_SLM_INDICATE_PIN, GPIO_DISCONNECTED); +#endif k_sleep(K_MSEC(100)); nrf_regulators_system_off(NRF_REGULATORS_NS); + assert(false); } static void on_modem_dfu_res(int dfu_res, void *ctx) @@ -333,6 +425,25 @@ static void check_app_fota_status(void) slm_fota_stage = FOTA_STAGE_COMPLETE; } +#if defined(CONFIG_LWM2M_CARRIER) +static atomic_t app_fota_status_checked; + +bool lwm2m_os_dfu_application_update_validate(void) +{ + if (atomic_cas(&app_fota_status_checked, false, true)) { + check_app_fota_status(); + } + + if ((slm_fota_type == DFU_TARGET_IMAGE_TYPE_MCUBOOT) && + (slm_fota_status == FOTA_STATUS_OK) && + (slm_fota_stage == FOTA_STAGE_COMPLETE)) { + return true; + } + + return false; +} +#endif /* CONFIG_LWM2M_CARRIER */ + int lte_auto_connect(void) { int err = 0; @@ -408,6 +519,17 @@ int start_execute(void) LOG_ERR("Failed to init at_host: %d", err); return err; } +#if POWER_PIN_IS_ENABLED + /* Do not directly enable the poweroff interrupt so that only a full toggle triggers + * power off. This is because power on is triggered on low level, so if the pin is held + * down until SLM is fully initialized releasing it would directly trigger the power off. + */ + err = configure_power_pin_interrupt(power_pin_callback_enable_poweroff, + GPIO_INT_EDGE_FALLING); +#endif + if (err) { + return err; + } k_work_queue_start(&slm_work_q, slm_wq_stack_area, K_THREAD_STACK_SIZEOF(slm_wq_stack_area), SLM_WQ_PRIORITY, NULL); @@ -431,9 +553,8 @@ int main(void) LOG_DBG("RR: 0x%08x", rr); k_work_init_delayable(&indicate_work, indicate_wk); - /* Init GPIOs */ - if (init_gpio() != 0) { - LOG_WRN("Failed to init gpio"); + if (init_gpios() != 0) { + LOG_WRN("Failed to init GPIO pins."); } /* Init and load settings */ if (slm_settings_init() != 0) { @@ -459,13 +580,22 @@ int main(void) } } +#if defined(CONFIG_LWM2M_CARRIER) + /* If LwM2M Carrier library is enabled, the library might have already validated the + * running application image; this should only be performed once. + */ + if (atomic_cas(&app_fota_status_checked, false, true)) { + check_app_fota_status(); + } +#else check_app_fota_status(); +#endif /* CONFIG_LWM2M_CARRIER */ #if defined(CONFIG_SLM_START_SLEEP) - if (!(rr & NRF_POWER_RESETREAS_OFF_MASK) && /* DETECT signal from GPIO*/ - !(rr & NRF_POWER_RESETREAS_DIF_MASK)) { /* Entering debug interface mode */ - enter_sleep(); - return 0; + + if (!(rr & NRF_POWER_RESETREAS_OFF_MASK)) { /* DETECT signal from GPIO */ + + enter_sleep_no_uninit(); } #endif /* CONFIG_SLM_START_SLEEP */ diff --git a/applications/serial_lte_modem/src/mqtt_c/slm_at_mqtt.c b/applications/serial_lte_modem/src/mqtt_c/slm_at_mqtt.c index a7be7f40d2e..8e33de4d496 100644 --- a/applications/serial_lte_modem/src/mqtt_c/slm_at_mqtt.c +++ b/applications/serial_lte_modem/src/mqtt_c/slm_at_mqtt.c @@ -9,10 +9,10 @@ #include #include #include +#include #include #include "slm_util.h" #include "slm_at_host.h" -#include "slm_native_tls.h" #include "slm_at_mqtt.h" LOG_MODULE_REGISTER(slm_mqtt, CONFIG_SLM_LOG_LEVEL); @@ -77,6 +77,24 @@ static int handle_mqtt_publish_evt(struct mqtt_client *const c, const struct mqt int size_read = 0; int ret; + /* Send QoS acknowledgments */ + if (evt->param.publish.message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { + const struct mqtt_puback_param ack = { + .message_id = evt->param.publish.message_id + }; + + mqtt_publish_qos1_ack(&client, &ack); + } else if (evt->param.publish.message.topic.qos == MQTT_QOS_2_EXACTLY_ONCE) { + const struct mqtt_pubrec_param ack = { + .message_id = evt->param.publish.message_id + }; + + mqtt_publish_qos2_receive(&client, &ack); + } + + /* SLM MQTT client does not track the packet identifiers, so MQTT_QOS_2_EXACTLY_ONCE + * promise is not kept. This deviates from MQTT v3.1.1. + */ rsp_send("\r\n#XMQTTMSG: %d,%d\r\n", evt->param.publish.message.topic.topic.size, evt->param.publish.message.payload.len); @@ -92,14 +110,6 @@ static int handle_mqtt_publish_evt(struct mqtt_client *const c, const struct mqt } while (ret >= 0 && size_read < evt->param.publish.message.payload.len); data_send("\r\n", 2); - /* Send QoS1 acknowledgment */ - if (evt->param.publish.message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { - const struct mqtt_puback_param ack = { - .message_id = evt->param.publish.message_id - }; - - mqtt_publish_qos1_ack(&client, &ack); - } return 0; } @@ -294,8 +304,7 @@ static int broker_init(void) .sa_family = AF_UNSPEC }; - err = util_resolve_host(0, mqtt_broker_url, mqtt_broker_port, ctx.family, - Z_LOG_OBJECT_PTR(slm_mqtt), &sa); + err = util_resolve_host(0, mqtt_broker_url, mqtt_broker_port, ctx.family, &sa); if (err) { return -EAGAIN; } @@ -430,6 +439,9 @@ static int do_mqtt_disconnect(void) static int do_mqtt_publish(uint8_t *msg, size_t msg_len) { + /* SLM MQTT client does not store packets, so we will not retransmit packets + * that are lacking response. This deviates from MQTT v3.1.1. + */ pub_param.message.payload.data = msg; pub_param.message.payload.len = msg_len; @@ -473,30 +485,30 @@ static int do_mqtt_subscribe(uint16_t op, return err; } -/* Handles AT#XMQTTCFG commands. */ -int handle_at_mqtt_config(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xmqttcfg, "AT#XMQTTCFG", handle_at_mqtt_config); +static int handle_at_mqtt_config(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t keep_alive = CONFIG_MQTT_KEEPALIVE; uint16_t clean_session = CONFIG_MQTT_CLEAN_SESSION; - uint32_t param_count = at_params_valid_count_get(&slm_at_param_list); switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: size_t clientid_sz = sizeof(mqtt_clientid); - err = util_string_get(&slm_at_param_list, 1, mqtt_clientid, &clientid_sz); + err = util_string_get(param_list, 1, mqtt_clientid, &clientid_sz); if (err) { return err; } if (param_count > 2) { - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &keep_alive); + err = at_params_unsigned_short_get(param_list, 2, &keep_alive); if (err) { return err; } } if (param_count > 3) { - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &clean_session); + err = at_params_unsigned_short_get(param_list, 3, &clean_session); if (err) { return err; } @@ -522,15 +534,16 @@ int handle_at_mqtt_config(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XMQTTCON commands. */ -int handle_at_mqtt_connect(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xmqttcon, "AT#XMQTTCON", handle_at_mqtt_connect); +static int handle_at_mqtt_connect(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -539,33 +552,31 @@ int handle_at_mqtt_connect(enum at_cmd_type cmd_type) size_t password_sz = sizeof(mqtt_password); size_t url_sz = sizeof(mqtt_broker_url); - err = util_string_get(&slm_at_param_list, 2, mqtt_username, &username_sz); + err = util_string_get(param_list, 2, mqtt_username, &username_sz); if (err) { return err; } else { ctx.username.utf8 = mqtt_username; ctx.username.size = strlen(mqtt_username); } - err = util_string_get(&slm_at_param_list, 3, mqtt_password, &password_sz); + err = util_string_get(param_list, 3, mqtt_password, &password_sz); if (err) { return err; } else { ctx.password.utf8 = mqtt_password; ctx.password.size = strlen(mqtt_password); } - err = util_string_get(&slm_at_param_list, 4, mqtt_broker_url, &url_sz); + err = util_string_get(param_list, 4, mqtt_broker_url, &url_sz); if (err) { return err; } - err = at_params_unsigned_short_get( - &slm_at_param_list, 5, &mqtt_broker_port); + err = at_params_unsigned_short_get(param_list, 5, &mqtt_broker_port); if (err) { return err; } ctx.sec_tag = INVALID_SEC_TAG; - if (at_params_valid_count_get(&slm_at_param_list) > 6) { - err = at_params_unsigned_int_get( - &slm_at_param_list, 6, &ctx.sec_tag); + if (param_count > 6) { + err = at_params_unsigned_int_get(param_list, 6, &ctx.sec_tag); if (err) { return err; } @@ -629,8 +640,9 @@ static int mqtt_datamode_callback(uint8_t op, const uint8_t *data, int len, uint return ret; } -/* Handles AT#XMQTTPUB commands. */ -int handle_at_mqtt_publish(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xmqttpub, "AT#XMQTTPUB", handle_at_mqtt_publish); +static int handle_at_mqtt_publish(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; @@ -639,7 +651,6 @@ int handle_at_mqtt_publish(enum at_cmd_type cmd_type) size_t topic_sz = MQTT_MAX_TOPIC_LEN; uint8_t pub_msg[SLM_MAX_PAYLOAD_SIZE]; size_t msg_sz = sizeof(pub_msg); - uint16_t param_count = at_params_valid_count_get(&slm_at_param_list); if (!ctx.connected) { return -ENOTCONN; @@ -647,25 +658,25 @@ int handle_at_mqtt_publish(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = util_string_get(&slm_at_param_list, 1, pub_topic, &topic_sz); + err = util_string_get(param_list, 1, pub_topic, &topic_sz); if (err) { return err; } pub_msg[0] = '\0'; if (param_count > 2) { - err = util_string_get(&slm_at_param_list, 2, pub_msg, &msg_sz); + err = util_string_get(param_list, 2, pub_msg, &msg_sz); if (err) { return err; } } if (param_count > 3) { - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &qos); + err = at_params_unsigned_short_get(param_list, 3, &qos); if (err) { return err; } } if (param_count > 4) { - err = at_params_unsigned_short_get(&slm_at_param_list, 4, &retain); + err = at_params_unsigned_short_get(param_list, 4, &retain); if (err) { return err; } @@ -709,8 +720,9 @@ int handle_at_mqtt_publish(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XMQTTSUB commands. */ -int handle_at_mqtt_subscribe(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xmqttsub, "AT#XMQTTSUB", handle_at_mqtt_subscribe); +static int handle_at_mqtt_subscribe(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err = -EINVAL; uint16_t qos; @@ -723,12 +735,12 @@ int handle_at_mqtt_subscribe(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) == 3) { - err = util_string_get(&slm_at_param_list, 1, topic, &topic_sz); + if (param_count == 3) { + err = util_string_get(param_list, 1, topic, &topic_sz); if (err < 0) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &qos); + err = at_params_unsigned_short_get(param_list, 2, &qos); if (err < 0) { return err; } @@ -750,8 +762,9 @@ int handle_at_mqtt_subscribe(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XMQTTUNSUB commands. */ -int handle_at_mqtt_unsubscribe(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xmqttunsub, "AT#XMQTTUNSUB", handle_at_mqtt_unsubscribe); +static int handle_at_mqtt_unsubscribe(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err = -EINVAL; char topic[MQTT_MAX_TOPIC_LEN]; @@ -763,9 +776,8 @@ int handle_at_mqtt_unsubscribe(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) == 2) { - err = util_string_get(&slm_at_param_list, 1, - topic, &topic_sz); + if (param_count == 2) { + err = util_string_get(param_list, 1, topic, &topic_sz); if (err < 0) { return err; } diff --git a/applications/serial_lte_modem/src/nativetls/CMakeLists.txt b/applications/serial_lte_modem/src/nativetls/CMakeLists.txt new file mode 100644 index 00000000000..6e55e600a0e --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +zephyr_include_directories(.) +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/slm_at_cmng.c) +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/slm_native_tls.c) diff --git a/applications/serial_lte_modem/src/nativetls/Kconfig b/applications/serial_lte_modem/src/nativetls/Kconfig new file mode 100644 index 00000000000..0f85f2bb1d3 --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/Kconfig @@ -0,0 +1,22 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +config SLM_NATIVE_TLS + bool "Use Zephyr's Mbed TLS for TLS connections" + +config SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE + int "Buffer space reserved for loading credentials" + default 4096 + help + Buffer space available for a single sec_tag when loading credentials for Mbed TLS. + +config SLM_NATIVE_TLS_CREDENTIAL_BUFFER_COUNT + int "Amount of buffers for loading credentials" + default 1 + range 1 2 + help + Amount of buffers available for loading sec_tag credentials for Mbed TLS. + TLS client needs the buffer only when connecting whereas TLS server needs the buffer as long as it is running. + Increase the value, if you need TLS client and server running simultaneously with different sec_tags. diff --git a/applications/serial_lte_modem/src/nativetls/slm_at_cmng.c b/applications/serial_lte_modem/src/nativetls/slm_at_cmng.c new file mode 100644 index 00000000000..a5ab39c1db0 --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/slm_at_cmng.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include "slm_native_tls.h" +#include "slm_at_host.h" +#include "slm_at_cmng.h" + +LOG_MODULE_REGISTER(slm_cmng, CONFIG_SLM_LOG_LEVEL); + +/**@brief List of supported opcode */ +enum slm_cmng_opcode { + AT_CMNG_OP_WRITE = 0, + AT_CMNG_OP_LIST = 1, + AT_CMNG_OP_DELETE = 3 +}; + +SLM_AT_CMD_CUSTOM(xcmng, "AT#XCMNG", handle_at_xcmng); +static int handle_at_xcmng(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) +{ + int err = -EINVAL; + uint16_t op, type; + nrf_sec_tag_t sec_tag; + + switch (cmd_type) { + case AT_CMD_TYPE_SET_COMMAND: + if (at_params_unsigned_short_get(param_list, 1, &op)) { + return -EINVAL; + } + if (param_count > 2 && + at_params_unsigned_int_get(param_list, 2, &sec_tag)) { + return -EINVAL; + } + if (param_count > 3 && (at_params_unsigned_short_get(param_list, 3, &type) || + type > SLM_AT_CMNG_TYPE_PSK_ID)) { + return -EINVAL; + } + if (op == AT_CMNG_OP_WRITE) { + const char *at_param; + size_t len; + + if (at_params_string_ptr_get(param_list, 4, &at_param, &len)) { + return -EINVAL; + } + err = slm_native_tls_store_credential(sec_tag, type, at_param, len); + } else if (op == AT_CMNG_OP_LIST) { + err = slm_native_tls_list_credentials(); + } else if (op == AT_CMNG_OP_DELETE) { + if (param_count < 4) { + return -EINVAL; + } + err = slm_native_tls_delete_credential(sec_tag, type); + } + break; + + default: + break; + } + + return err; +} diff --git a/applications/serial_lte_modem/src/nativetls/slm_at_cmng.h b/applications/serial_lte_modem/src/nativetls/slm_at_cmng.h new file mode 100644 index 00000000000..d73b5496403 --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/slm_at_cmng.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef SLM_AT_CMNG_ +#define SLM_AT_CMNG_ + +/**@file slm_at_cmng.h + * + * @brief SLM-specific AT command for credential storing. + * @{ + */ + +enum slm_cmng_type { + SLM_AT_CMNG_TYPE_CA_CERT, + SLM_AT_CMNG_TYPE_CLIENT_CERT, + SLM_AT_CMNG_TYPE_CLIENT_KEY, + SLM_AT_CMNG_TYPE_PSK, + SLM_AT_CMNG_TYPE_PSK_ID, + SLM_AT_CMNG_TYPE_COUNT +}; + +/** @} */ + +#endif /* SLM_AT_CMNG_ */ diff --git a/applications/serial_lte_modem/src/nativetls/slm_native_tls.c b/applications/serial_lte_modem/src/nativetls/slm_native_tls.c new file mode 100644 index 00000000000..ebdc05030a8 --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/slm_native_tls.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include "slm_native_tls.h" +#include "slm_at_host.h" +#include "slm_at_cmng.h" + +LOG_MODULE_REGISTER(slm_native_tls, CONFIG_SLM_LOG_LEVEL); + +/* Stores certificates and other credentials in the Zephyr settings storage. + * Storage is organized as slm-keys//. + * When native TLS connection is created, credentials under are loaded to + * TLS credential management for Mbed TLS. + */ + +#define SLM_KEYS_MAX_SIZE sizeof("slm-keys/2147483647/0") + +/* Loaded for TLS credential management. */ +struct tls_cred_buf { + uint8_t buf[CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE]; /* Credentials. */ + sec_tag_t sec_tag; /* sec_tag of the credentials in buf. */ + uint8_t type_flags; /* Credential types loaded in buf (1 << slm_cmng_type). */ +}; +static struct tls_cred_buf cred_buf[CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_COUNT] = { + [0 ... CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_COUNT - 1] = { + .sec_tag = -1 + } +}; +static uint8_t cred_buf_next; /* Index of next cred_buf to use. */ + +/* Parameter for load_credential_cb. */ +struct load_credential_params { + sec_tag_t sec_tag; + uint8_t *credential_flags; + uint8_t *buf; + size_t buf_len; +}; + +enum tls_credential_type slm_cmng_to_tls_cred(enum slm_cmng_type type) +{ + switch (type) { + case SLM_AT_CMNG_TYPE_CA_CERT: return TLS_CREDENTIAL_CA_CERTIFICATE; + case SLM_AT_CMNG_TYPE_CLIENT_CERT: return TLS_CREDENTIAL_SERVER_CERTIFICATE; + case SLM_AT_CMNG_TYPE_CLIENT_KEY: return TLS_CREDENTIAL_PRIVATE_KEY; + case SLM_AT_CMNG_TYPE_PSK: return TLS_CREDENTIAL_PSK; + case SLM_AT_CMNG_TYPE_PSK_ID: return TLS_CREDENTIAL_PSK_ID; + default: return TLS_CREDENTIAL_NONE; + } +} + +/* Load credentials to TLS credential management. + * Called for every (slm-keys//). + */ +static int load_credential_cb(const char *key, size_t len, settings_read_cb read_cb, void *cb_arg, + void *param) +{ + int err; + size_t setting_length; + unsigned long type; + struct load_credential_params *lcp = (struct load_credential_params *)param; + + type = strtoul(key, NULL, 10); + if (type >= SLM_AT_CMNG_TYPE_COUNT) { + return -EFAULT; + } + if (len > lcp->buf_len) { + return -E2BIG; + } + + setting_length = read_cb(cb_arg, lcp->buf, len); + if (setting_length != len) { + return -EFAULT; + } + + /* PEM formatted certificate and keys need to be null-terminated for Mbed TLS. */ + if (type <= SLM_AT_CMNG_TYPE_CLIENT_KEY && lcp->buf[setting_length - 1] != '\0' && + lcp->buf_len > setting_length) { + lcp->buf[setting_length] = '\0'; + setting_length++; + } + + err = tls_credential_add(lcp->sec_tag, slm_cmng_to_tls_cred(type), lcp->buf, + setting_length); + if (err) { + LOG_ERR("Failed tls_credential_add: %d,%lu", lcp->sec_tag, type); + return err; + } + + /* Keep track of the loaded credentials types. */ + *lcp->credential_flags |= 1 << type; + + /* Update buf to accommodate other credentials under the sec_tag. */ + lcp->buf += setting_length; + lcp->buf_len -= setting_length; + + LOG_DBG("Loaded credential: %d,%lu", lcp->sec_tag, type); + + return 0; +} + +/* List SLM credentials stored in Zephyr settings storage. + * Called for every (slm-keys/). + */ +static int list_credentials_cb(const char *key, size_t len, settings_read_cb read_cb, void *cb_arg, + void *param) +{ + ARG_UNUSED(len); + ARG_UNUSED(read_cb); + ARG_UNUSED(cb_arg); + ARG_UNUSED(param); + + int err; + char buf[sizeof("#XCMNG: 2147483647,0\r\n")]; + + err = snprintf(buf, sizeof(buf), "#XCMNG: %s\r\n", key); + if (err < 0) { + return err; + } else if (err >= sizeof(buf)) { + return -E2BIG; + } + + char *ptr = buf; + + /* Format similarly to %CMNG. */ + while (*ptr) { + if (*ptr == '/') { + *ptr = ','; + } + ptr++; + } + + slm_at_send_str(buf); + if (err) { + LOG_ERR("Failed slm_at_send: %d", err); + } + + return err; +} + +/* Called for every (slm-keys//). */ +static int get_setting_len_cb(const char *key, size_t len, settings_read_cb read_cb, void *cb_arg, + void *param) +{ + ARG_UNUSED(key); + ARG_UNUSED(read_cb); + ARG_UNUSED(cb_arg); + + size_t *param_len = param; + *param_len += len; + + return 0; +} + +static int get_credentials_len(sec_tag_t sec_tag, size_t *len) +{ + char key[SLM_KEYS_MAX_SIZE]; + const int err = snprintf(key, sizeof(key), "slm-keys/%d", sec_tag); + + if (err < 0) { + return err; + } + + *len = 0; + return settings_load_subtree_direct(key, get_setting_len_cb, len); +} + +static struct tls_cred_buf *get_tls_cred_buf(sec_tag_t sec_tag) +{ + for (int i = 0; i < ARRAY_SIZE(cred_buf); ++i) { + if (cred_buf[i].sec_tag == sec_tag) { + return &cred_buf[i]; + } + } + + return NULL; +} + +static int unload_tls_cred_buf(sec_tag_t sec_tag) +{ + struct tls_cred_buf *cred = get_tls_cred_buf(sec_tag); + + if (cred == NULL || sec_tag == -1) { + return 0; + } + + /* Delete previously loaded credentials from the credential store. */ + for (enum slm_cmng_type i = SLM_AT_CMNG_TYPE_CA_CERT; i != SLM_AT_CMNG_TYPE_COUNT; ++i) { + if (cred->type_flags & (1 << i)) { + const int err = + tls_credential_delete(cred->sec_tag, slm_cmng_to_tls_cred(i)); + + if (err) { + LOG_ERR("Failed tls_credential_delete: %d, credential: %d,%d", + err, cred->sec_tag, i); + + return err; + } + } + } + cred->sec_tag = -1; + cred->type_flags = 0; + + return 0; +} + +int slm_native_tls_store_credential(sec_tag_t sec_tag, uint16_t type, const void *data, size_t len) +{ + char key[SLM_KEYS_MAX_SIZE]; + int err; + size_t cred_len = 0; + + err = snprintf(key, sizeof(key), "slm-keys/%d/%d", sec_tag, type); + if (err < 0) { + return err; + } + + err = get_credentials_len(sec_tag, &cred_len); + if (err) { + return err; + } + + /* Verify that the stored credentials could be loaded. */ + const uint8_t null_termination = type <= SLM_AT_CMNG_TYPE_CLIENT_KEY ? 1 : 0; + + if ((cred_len + len + null_termination) > CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE) { + LOG_ERR("Increase CONFIG_SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE."); + return -E2BIG; + } + + err = settings_save_one(key, data, len); + if (err) { + LOG_ERR("Failed settings_save_one: %d", err); + return err; + } + + return unload_tls_cred_buf(sec_tag); +} + +int slm_native_tls_list_credentials(void) +{ + return settings_load_subtree_direct("slm-keys", list_credentials_cb, NULL); +} + +int slm_native_tls_load_credentials(sec_tag_t sec_tag) +{ + int err; + struct tls_cred_buf *cred = get_tls_cred_buf(sec_tag); + + if (cred) { + /* Already loaded. */ + return 0; + } + + /* Take the next credential buf to use. */ + cred = &cred_buf[cred_buf_next]; + cred_buf_next = (cred_buf_next + 1) % ARRAY_SIZE(cred_buf); + err = unload_tls_cred_buf(cred->sec_tag); + if (err) { + return err; + } + cred->sec_tag = sec_tag; + + char key[SLM_KEYS_MAX_SIZE]; + + err = snprintf(key, sizeof(key), "slm-keys/%d", cred->sec_tag); + if (err < 0) { + return err; + } + + struct load_credential_params params = { + .sec_tag = cred->sec_tag, + .credential_flags = &(cred->type_flags), + .buf = cred->buf, + .buf_len = sizeof(cred->buf) + }; + + return settings_load_subtree_direct(key, load_credential_cb, (void *)¶ms); +} + +int slm_native_tls_delete_credential(sec_tag_t sec_tag, uint16_t type) +{ + int err; + char key[SLM_KEYS_MAX_SIZE]; + + err = snprintf(key, sizeof(key), "slm-keys/%d/%d", sec_tag, type); + if (err < 0) { + return err; + } + + err = settings_delete(key); + if (err) { + return err; + } + + return unload_tls_cred_buf(sec_tag); +} diff --git a/applications/serial_lte_modem/src/nativetls/slm_native_tls.h b/applications/serial_lte_modem/src/nativetls/slm_native_tls.h new file mode 100644 index 00000000000..c9988ecc1da --- /dev/null +++ b/applications/serial_lte_modem/src/nativetls/slm_native_tls.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef SLM_NATIVE_TLS_ +#define SLM_NATIVE_TLS_ + +/**@file slm_native_tls.h + * + * @brief Utility functions for serial LTE modem native TLS socket + * @{ + */ + +#include +#include "slm_trap_macros.h" + +/** + * @brief Store credential to Zephyr settings storage. + * + * @param[in] sec_tag sec_tag under which the credential is stored. + * @param[in] type Type of the credential to be stored. + * @param[in] data Pointer to the credential data. + * @param[in] len Length of the credential data. + * + * @retval 0 If succeeded. + * @retval -E2BIG if credentials under sec_tag would exceed SLM_NATIVE_TLS_CREDENTIAL_BUFFER_SIZE. + * @retval -errno Negative errno for other failures. + */ +int slm_native_tls_store_credential(sec_tag_t sec_tag, uint16_t type, const void *data, size_t len); + +/** + * @brief List credential sec_tags and types from Zephyr settings storage. + * + * @retval 0 If succeeded. + * @retval -errno Negative errno for failures. + */ +int slm_native_tls_list_credentials(void); + +/** + * @brief Load credentials from Zephyr settings storage to TLS credentials storage for Mbed TLS. + * + * @param[in] sec_tag sec_tag under which the credentials are loaded. + * + * @retval 0 If succeeded. + * @retval -errno Negative errno for failures. + */ +int slm_native_tls_load_credentials(sec_tag_t sec_tag); + +/** + * @brief Delete credential from Zephyr settings storage. + * + * @param[in] sec_tag sec_tag under which the credential is deleted. + * @param[in] type Type of the credential to be deleted. + * + * @retval 0 If succeeded. + * @retval -errno Negative errno for failures. + */ +int slm_native_tls_delete_credential(sec_tag_t sec_tag, uint16_t type); + +/** @} */ + +#endif /* SLM_NATIVE_TLS_ */ diff --git a/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.c b/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.c index 568fbbbb212..89a78fe3eed 100644 --- a/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.c +++ b/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.c @@ -19,9 +19,6 @@ LOG_MODULE_REGISTER(slm_nrfcloud, CONFIG_SLM_LOG_LEVEL); -#define SERVICE_INFO_GNSS \ - "{\"state\":{\"reported\":{\"device\": {\"serviceInfo\":{\"ui\":[\"GNSS\"]}}}}}" - #define MODEM_AT_RSP \ "{\"appId\":\"MODEM\", \"messageType\":\"RSP\", \"data\":\"%s\"}" @@ -104,10 +101,10 @@ static void ncell_meas_mon(const char *notify) char mcc[4] = {0}; char tac[9] = {0}; unsigned int ncells_count = 0; + struct at_param_list *list = NULL; nrfcloud_ncellmeas_done = false; - at_params_list_clear(&slm_at_param_list); - err = at_parser_params_from_str(notify, NULL, &slm_at_param_list); + err = slm_get_at_param_list(notify, &list); if (err == -E2BIG) { LOG_WRN("%%NCELLMEAS result notification truncated" " because its parameter count exceeds CONFIG_SLM_AT_MAX_PARAM."); @@ -116,7 +113,7 @@ static void ncell_meas_mon(const char *notify) } /* parse status, 0: success 1: fail */ - err = at_params_int_get(&slm_at_param_list, 1, &ncellmeas_status); + err = at_params_int_get(list, 1, &ncellmeas_status); if (err) { goto exit; } @@ -125,7 +122,7 @@ static void ncell_meas_mon(const char *notify) err = -EAGAIN; goto exit; } - param_count = at_params_valid_count_get(&slm_at_param_list); + param_count = at_params_valid_count_get(list); if (param_count < MAX_PARAM_CELL) { /* at least current cell */ LOG_ERR("Missing param in NCELLMEAS notification"); err = -EAGAIN; @@ -134,7 +131,7 @@ static void ncell_meas_mon(const char *notify) /* parse Cell ID */ size = sizeof(cid); - err = util_string_get(&slm_at_param_list, 2, cid, &size); + err = util_string_get(list, 2, cid, &size); if (err) { goto exit; } @@ -145,7 +142,7 @@ static void ncell_meas_mon(const char *notify) /* parse PLMN */ size = sizeof(plmn); - err = util_string_get(&slm_at_param_list, 3, plmn, &size); + err = util_string_get(list, 3, plmn, &size); if (err) { goto exit; } @@ -161,7 +158,7 @@ static void ncell_meas_mon(const char *notify) /* parse TAC */ size = sizeof(tac); - err = util_string_get(&slm_at_param_list, 4, tac, &size); + err = util_string_get(list, 4, tac, &size); if (err) { goto exit; } @@ -174,25 +171,24 @@ static void ncell_meas_mon(const char *notify) nrfcloud_cell_data.current_cell.timing_advance = NRF_CLOUD_LOCATION_CELL_OMIT_TIME_ADV; /* parse EARFCN */ - err = at_params_unsigned_int_get(&slm_at_param_list, 6, - &nrfcloud_cell_data.current_cell.earfcn); + err = at_params_unsigned_int_get(list, 6, &nrfcloud_cell_data.current_cell.earfcn); if (err) { goto exit; } /* parse PCI */ - err = at_params_unsigned_short_get(&slm_at_param_list, 7, - &nrfcloud_cell_data.current_cell.phys_cell_id); + err = at_params_unsigned_short_get(list, 7, + &nrfcloud_cell_data.current_cell.phys_cell_id); if (err) { goto exit; } /* parse RSRP and RSRQ */ - err = at_params_short_get(&slm_at_param_list, 8, &nrfcloud_cell_data.current_cell.rsrp); + err = at_params_short_get(list, 8, &nrfcloud_cell_data.current_cell.rsrp); if (err < 0) { goto exit; } - err = at_params_short_get(&slm_at_param_list, 9, &nrfcloud_cell_data.current_cell.rsrq); + err = at_params_short_get(list, 9, &nrfcloud_cell_data.current_cell.rsrq); if (err < 0) { goto exit; } @@ -204,27 +200,26 @@ static void ncell_meas_mon(const char *notify) const unsigned int offset = MAX_PARAM_CELL + i * MAX_PARAM_NCELL; /* parse n_earfcn */ - err = at_params_unsigned_int_get(&slm_at_param_list, offset, - &nrfcloud_ncells[i].earfcn); + err = at_params_unsigned_int_get(list, offset, &nrfcloud_ncells[i].earfcn); if (err < 0) { goto exit; } /* parse n_phys_cell_id */ - err = at_params_unsigned_short_get(&slm_at_param_list, offset + 1, + err = at_params_unsigned_short_get(list, offset + 1, &nrfcloud_ncells[i].phys_cell_id); if (err < 0) { goto exit; } /* parse n_rsrp */ - err = at_params_short_get(&slm_at_param_list, offset + 2, &nrfcloud_ncells[i].rsrp); + err = at_params_short_get(list, offset + 2, &nrfcloud_ncells[i].rsrp); if (err < 0) { goto exit; } /* parse n_rsrq */ - err = at_params_short_get(&slm_at_param_list, offset + 3, &nrfcloud_ncells[i].rsrq); + err = at_params_short_get(list, offset + 3, &nrfcloud_ncells[i].rsrq); if (err < 0) { goto exit; } @@ -261,7 +256,7 @@ static void loc_req_wk(struct k_work *work) if (!err) { err = nrf_cloud_location_request( nrfcloud_cell_pos ? &nrfcloud_cell_data : NULL, - nrfcloud_wifi_pos ? &nrfcloud_wifi_data : NULL, true, NULL); + nrfcloud_wifi_pos ? &nrfcloud_wifi_data : NULL, NULL, NULL); if (err) { LOG_ERR("Failed to request nRF Cloud location (%d).", err); } else { @@ -300,23 +295,6 @@ static int do_cloud_send_msg(const char *message, int len) static void on_cloud_evt_ready(void) { - int err; - - if (slm_nrf_cloud_send_location) { - struct nrf_cloud_tx_data msg = { - .data.ptr = SERVICE_INFO_GNSS, - .data.len = strlen(SERVICE_INFO_GNSS), - .topic_type = NRF_CLOUD_TOPIC_STATE, - .qos = MQTT_QOS_0_AT_MOST_ONCE - }; - - /* Update nRF Cloud with GPS service info signifying GPS capabilities. */ - err = nrf_cloud_send(&msg); - if (err) { - LOG_WRN("Failed to send message to cloud, error: %d", err); - } - } - slm_nrf_cloud_ready = true; rsp_send("\r\n#XNRFCLOUD: %d,%d\r\n", slm_nrf_cloud_ready, slm_nrf_cloud_send_location); #if defined(CONFIG_NRF_CLOUD_LOCATION) @@ -570,8 +548,10 @@ static int nrf_cloud_datamode_callback(uint8_t op, const uint8_t *data, int len, return ret; } -/* Handles the AT#XNRFCLOUD commands. */ -int handle_at_nrf_cloud(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xnrfcloud_set, "AT#XNRFCLOUD=", handle_at_nrf_cloud); +SLM_AT_CMD_CUSTOM(xnrfcloud_read, "AT#XNRFCLOUD?", handle_at_nrf_cloud); +static int handle_at_nrf_cloud(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { enum slm_nrfcloud_operation { SLM_NRF_CLOUD_DISCONNECT, @@ -584,14 +564,13 @@ int handle_at_nrf_cloud(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err < 0) { return err; } if (op == SLM_NRF_CLOUD_CONNECT && !slm_nrf_cloud_ready) { - if (at_params_valid_count_get(&slm_at_param_list) > 2) { - err = at_params_unsigned_short_get(&slm_at_param_list, 2, - &send_location); + if (param_count > 2) { + err = at_params_unsigned_short_get(param_list, 2, &send_location); if (send_location != 0 && send_location != 1) { err = -EINVAL; } @@ -648,11 +627,11 @@ int handle_at_nrf_cloud(enum at_cmd_type cmd_type) #if defined(CONFIG_NRF_CLOUD_LOCATION) -/* Handles the AT#XNRFCLOUDPOS command. */ -int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xnrfcloudpos, "AT#XNRFCLOUDPOS", handle_at_nrf_cloud_pos); +static int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err; - const uint32_t param_count = at_params_valid_count_get(&slm_at_param_list); uint16_t cell_pos, wifi_pos; if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { @@ -674,12 +653,12 @@ int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type) return -EINVAL; } - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &cell_pos); + err = at_params_unsigned_short_get(param_list, 1, &cell_pos); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &wifi_pos); + err = at_params_unsigned_short_get(param_list, 2, &wifi_pos); if (err) { return err; } @@ -725,7 +704,7 @@ int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type) /* Parse the MAC address. */ len = sizeof(mac_addr_str); err = at_params_string_get( - &slm_at_param_list, param_idx, mac_addr_str, &len); + param_list, param_idx, mac_addr_str, &len); if (!err && (len != sizeof(mac_addr_str) || sscanf(mac_addr_str, WIFI_MAC_ADDR_TEMPLATE, &mac_addr[0], &mac_addr[1], &mac_addr[2], @@ -744,7 +723,7 @@ int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type) ap->mac_length = WIFI_MAC_ADDR_LEN; /* Parse the RSSI, if present. */ - if (!at_params_int_get(&slm_at_param_list, param_idx + 1, &rssi)) { + if (!at_params_int_get(param_list, param_idx + 1, &rssi)) { ++param_idx; const int rssi_min = -128; const int rssi_max = 0; diff --git a/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.h b/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.h index 78bbf78f942..51eb08ceda1 100644 --- a/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.h +++ b/applications/serial_lte_modem/src/nrfcloud/slm_at_nrfcloud.h @@ -23,16 +23,6 @@ extern bool slm_nrf_cloud_ready; /* Whether to send the device's location to nRF Cloud. */ extern bool slm_nrf_cloud_send_location; -/* Handles the AT#XNRFCLOUD commands. */ -int handle_at_nrf_cloud(enum at_cmd_type cmd_type); - -#if defined(CONFIG_NRF_CLOUD_LOCATION) - -/* Handles the AT#XNRFCLOUDPOS command. */ -int handle_at_nrf_cloud_pos(enum at_cmd_type cmd_type); - -#endif /* CONFIG_NRF_CLOUD_LOCATION */ - /** * @brief Initialize nRF Cloud AT command parser. * diff --git a/applications/serial_lte_modem/src/slm_at_cmng.c b/applications/serial_lte_modem/src/slm_at_cmng.c deleted file mode 100644 index 6f738ff6ca4..00000000000 --- a/applications/serial_lte_modem/src/slm_at_cmng.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include -#include -#include -#include -#include "slm_util.h" -#include "slm_native_tls.h" -#include "slm_at_host.h" -#include "slm_at_cmng.h" - -LOG_MODULE_REGISTER(slm_cmng, CONFIG_SLM_LOG_LEVEL); - -/**@brief List of supported opcode */ -enum slm_cmng_opcode { - AT_CMNG_OP_WRITE, - AT_CMNG_OP_LIST, - AT_CMNG_OP_READ, - AT_CMNG_OP_DELETE -}; - -/**@brief List of supported type */ -enum slm_cmng_type { - AT_CMNG_TYPE_CA_CERT, - AT_CMNG_TYPE_CERT, - AT_CMNG_TYPE_PRIV, - AT_CMNG_TYPE_PSK, - AT_CMNG_TYPE_PSK_ID, -}; - -/* Handles AT#XCMNG command. */ -int handle_at_xcmng(enum at_cmd_type cmd_type) -{ - int err = -EINVAL; - uint16_t op, type; - nrf_sec_tag_t sec_tag; - uint8_t *content; - size_t len = SLM_AT_MAX_RSP_LEN; - - switch (cmd_type) { - case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) < 2) { - LOG_ERR("Parameter missed"); - return -EINVAL; - } - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); - if (err < 0) { - LOG_ERR("Fail to get op parameter: %d", err); - return err; - } - if (op > AT_CMNG_OP_DELETE) { - LOG_ERR("Wrong XCMNG operation: %d", op); - return -EPERM; - } - if (op == AT_CMNG_OP_LIST) { - /* Currently not support list command */ - LOG_ERR("XCMNG List is not supported"); - return -EPERM; - } - if (at_params_valid_count_get(&slm_at_param_list) < 4) { - /* READ, WRITE, DELETE requires sec_tag and type */ - LOG_ERR("Parameter missed"); - return -EINVAL; - } - err = at_params_unsigned_int_get(&slm_at_param_list, 2, &sec_tag); - if (err < 0) { - LOG_ERR("Fail to get sec_tag parameter: %d", err); - return err; - }; - if (sec_tag > MAX_SLM_SEC_TAG) { - LOG_ERR("Invalid security tag: %d", sec_tag); - return -EINVAL; - } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &type); - if (err < 0) { - LOG_ERR("Fail to get type parameter: %d", err); - return err; - }; - if (op == AT_CMNG_OP_WRITE) { - if (at_params_valid_count_get(&slm_at_param_list) < 5) { - /* WRITE requires sec_tag, type and content */ - LOG_ERR("Parameter missed"); - return -EINVAL; - } - content = k_malloc(SLM_AT_MAX_RSP_LEN); - err = util_string_get(&slm_at_param_list, 4, content, - &len); - if (err != 0) { - LOG_ERR("Failed to get content"); - k_free(content); - return err; - } - err = modem_key_mgmt_write( - slm_tls_map_sectag(sec_tag, type), - 0, content, len); - if (err != 0) { - LOG_ERR("FAILED! modem_key_mgmt_write() = %d", - err); - } - k_free(content); - } else if (op == AT_CMNG_OP_READ) { - if (type == AT_CMNG_TYPE_CERT || - type == AT_CMNG_TYPE_PRIV || - type == AT_CMNG_TYPE_PSK) { - /* Not supported */ - LOG_ERR("Not support READ for type: %d", type); - return -EPERM; - } - content = k_malloc(SLM_AT_MAX_RSP_LEN); - err = modem_key_mgmt_read( - slm_tls_map_sectag(sec_tag, type), - 0, content, &len); - if (err != 0) { - LOG_ERR("FAILED! modem_key_mgmt_read() = %d", - err); - } else { - *(content + len) = '\0'; - rsp_send("%%CMNG: %d,%d,\"\"," - "\"%s\"\r\n", sec_tag, type, content); - } - k_free(content); - } else if (op == AT_CMNG_OP_DELETE) { - err = modem_key_mgmt_delete( - slm_tls_map_sectag(sec_tag, type), 0); - if (err != 0) { - LOG_ERR("FAILED! modem_key_mgmt_delete() = %d", - err); - } - } - break; - - default: - break; - } - - return err; -} - -/**@brief API to initialize CMNG AT commands handler - */ -int slm_at_cmng_init(void) -{ - return 0; -} - -/**@brief API to uninitialize CMNG AT commands handler - */ -int slm_at_cmng_uninit(void) -{ - return 0; -} diff --git a/applications/serial_lte_modem/src/slm_at_cmng.h b/applications/serial_lte_modem/src/slm_at_cmng.h deleted file mode 100644 index ff302c06042..00000000000 --- a/applications/serial_lte_modem/src/slm_at_cmng.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef SLM_AT_CMNG_ -#define SLM_AT_CMNG_ - -/**@file slm_at_cmng.h - * - * @brief Vendor-specific AT command for CMNG service. - * @{ - */ - -/** - * @brief Initialize CMNG AT command parser. - * - * @retval 0 If the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int slm_at_cmng_init(void); - -/** - * @brief Uninitialize CMNG AT command parser. - * - * @retval 0 If the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int slm_at_cmng_uninit(void); -/** @} */ - -#endif /* SLM_AT_CMNG_ */ diff --git a/applications/serial_lte_modem/src/slm_at_commands.c b/applications/serial_lte_modem/src/slm_at_commands.c index fd3bc29948a..cb8de61f1e5 100644 --- a/applications/serial_lte_modem/src/slm_at_commands.c +++ b/applications/serial_lte_modem/src/slm_at_commands.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +32,6 @@ #include "slm_at_icmp.h" #include "slm_at_sms.h" #include "slm_at_fota.h" -#include "slm_uart_handler.h" #if defined(CONFIG_SLM_NATIVE_TLS) #include "slm_at_cmng.h" #endif @@ -58,18 +59,15 @@ #if defined(CONFIG_SLM_CARRIER) #include "slm_at_carrier.h" #endif -#if defined(CONFIG_LWM2M_CARRIER_SETTINGS) -#include "slm_at_carrier_cfg.h" -#endif #if defined(CONFIG_SLM_PPP) #include "slm_ppp.h" #endif +#if defined(CONFIG_SLM_CMUX) +#include "slm_cmux.h" +#endif LOG_MODULE_REGISTER(slm_at, CONFIG_SLM_LOG_LEVEL); -/* This delay is necessary for at_host to send response message in low baud rate. */ -#define SLM_UART_RESPONSE_DELAY 50 - /** @brief Shutdown modes. */ enum sleep_modes { SLEEP_MODE_INVALID, @@ -80,19 +78,16 @@ enum sleep_modes { /** @brief AT command handler type. */ typedef int (*slm_at_handler_t) (enum at_cmd_type); -static struct slm_work_info { - struct k_work_delayable sleep_work; - uint32_t data; -} slm_work; +#if POWER_PIN_IS_ENABLED +static struct { + struct k_work_delayable work; + uint32_t mode; +} sleep; +#endif -/* global functions defined in different files */ -void enter_idle(void); -void enter_sleep(void); -void enter_shutdown(void); bool verify_datamode_control(uint16_t time_limit, uint16_t *time_limit_min); -/** @return Whether the modem is in the given functional mode. */ -static bool is_modem_functional_mode(enum lte_lc_func_mode mode) +bool slm_is_modem_functional_mode(enum lte_lc_func_mode mode) { int cfun; int rc = slm_util_at_scanf("AT+CFUN?", "+CFUN: %d", &cfun); @@ -100,26 +95,22 @@ static bool is_modem_functional_mode(enum lte_lc_func_mode mode) return (rc == 1 && cfun == mode); } -static void modem_power_off(void) +int slm_power_off_modem(void) { - /* First check whether the modem has already been turned off by the MCU. */ - if (!is_modem_functional_mode(LTE_LC_FUNC_MODE_POWER_OFF)) { - - /* "[...] there may be a delay until modem is disconnected from the network." - * https://infocenter.nordicsemi.com/topic/ps_nrf9160/chapters/pmu/doc/operationmodes/system_off_mode.html - * This will return once the modem responds, which means it has actually - * stopped. This has been observed to take between 1 and 2 seconds. - */ - slm_util_at_printf("AT+CFUN=0"); - } + /* "[...] there may be a delay until modem is disconnected from the network." + * https://infocenter.nordicsemi.com/topic/ps_nrf9160/chapters/pmu/doc/operationmodes/system_off_mode.html + * This will return once the modem responds, which means it has actually stopped. + * This has been observed to take between 1 and 2 seconds when it is not already stopped. + */ + return slm_util_at_printf("AT+CFUN=0"); } -/* Handles AT#XSLMVER command. */ -static int handle_at_slmver(enum at_cmd_type type) +SLM_AT_CMD_CUSTOM(xslmver, "AT#XSLMVER", handle_at_slmver); +static int handle_at_slmver(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { int ret = -EINVAL; - if (type == AT_CMD_TYPE_SET_COMMAND) { + if (cmd_type == AT_CMD_TYPE_SET_COMMAND) { char *libmodem = nrf_modem_build_version(); if (strlen(CONFIG_SLM_CUSTOMER_VERSION) > 0) { @@ -136,45 +127,38 @@ static int handle_at_slmver(enum at_cmd_type type) return ret; } -static void go_sleep_wk(struct k_work *work) -{ - ARG_UNUSED(work); +#if POWER_PIN_IS_ENABLED - if (slm_work.data == SLEEP_MODE_IDLE) { - if (slm_uart_power_off() == 0) { - enter_idle(); +static void go_sleep_wk(struct k_work *) +{ + if (sleep.mode == SLEEP_MODE_IDLE) { + if (slm_at_host_power_off() == 0) { + slm_enter_idle(); } else { LOG_ERR("failed to power off UART"); } - } else if (slm_work.data == SLEEP_MODE_DEEP) { - slm_at_host_uninit(); - - /* Only power off the modem if it has not been put - * in flight mode to allow reducing NVM wear. - */ - if (!is_modem_functional_mode(LTE_LC_FUNC_MODE_OFFLINE)) { - modem_power_off(); - } - enter_sleep(); + } else if (sleep.mode == SLEEP_MODE_DEEP) { + slm_enter_sleep(); } } -/* Handles AT#XSLEEP commands. */ -static int handle_at_sleep(enum at_cmd_type type) +SLM_AT_CMD_CUSTOM(xsleep, "AT#XSLEEP", handle_at_sleep); +static int handle_at_sleep(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret = -EINVAL; - if (type == AT_CMD_TYPE_SET_COMMAND) { - ret = at_params_unsigned_int_get(&slm_at_param_list, 1, &slm_work.data); + if (cmd_type == AT_CMD_TYPE_SET_COMMAND) { + ret = at_params_unsigned_int_get(param_list, 1, &sleep.mode); if (ret) { return -EINVAL; } - if (slm_work.data == SLEEP_MODE_DEEP || slm_work.data == SLEEP_MODE_IDLE) { - k_work_reschedule(&slm_work.sleep_work, K_MSEC(100)); + if (sleep.mode == SLEEP_MODE_DEEP || sleep.mode == SLEEP_MODE_IDLE) { + k_work_reschedule(&sleep.work, SLM_UART_RESPONSE_DELAY); } else { ret = -EINVAL; } - } else if (type == AT_CMD_TYPE_TEST_COMMAND) { + } else if (cmd_type == AT_CMD_TYPE_TEST_COMMAND) { rsp_send("\r\n#XSLEEP: (%d,%d)\r\n", SLEEP_MODE_DEEP, SLEEP_MODE_IDLE); ret = 0; } @@ -182,48 +166,64 @@ static int handle_at_sleep(enum at_cmd_type type) return ret; } -/* Handles AT#XSHUTDOWN command. */ -static int handle_at_shutdown(enum at_cmd_type type) +#endif /* POWER_PIN_IS_ENABLED */ + +static void final_call(void (*func)(void)) { - int ret = -EINVAL; + /* Delegate the final call to a worker so that the "OK" response is properly sent. */ + static struct k_work_delayable worker; - if (type == AT_CMD_TYPE_SET_COMMAND) { - rsp_send_ok(); - k_sleep(K_MSEC(SLM_UART_RESPONSE_DELAY)); - slm_at_host_uninit(); - modem_power_off(); - enter_shutdown(); + k_work_init_delayable(&worker, (k_work_handler_t)func); + k_work_schedule(&worker, SLM_UART_RESPONSE_DELAY); +} + +static void slm_shutdown(void) +{ + slm_at_host_uninit(); + slm_power_off_modem(); + LOG_PANIC(); + slm_enter_shutdown(); +} + +SLM_AT_CMD_CUSTOM(xshutdown, "AT#XSHUTDOWN", handle_at_shutdown); +static int handle_at_shutdown(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) +{ + if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { + return -EINVAL; } - return ret; + final_call(slm_shutdown); + return 0; } -/* Handles AT#XRESET command. */ -static int handle_at_reset(enum at_cmd_type type) +FUNC_NORETURN void slm_reset(void) { - int ret = -EINVAL; + slm_at_host_uninit(); + slm_power_off_modem(); + LOG_PANIC(); + sys_reboot(SYS_REBOOT_COLD); +} - if (type == AT_CMD_TYPE_SET_COMMAND) { - rsp_send_ok(); - k_sleep(K_MSEC(SLM_UART_RESPONSE_DELAY)); - slm_at_host_uninit(); - modem_power_off(); - LOG_PANIC(); - sys_reboot(SYS_REBOOT_COLD); +SLM_AT_CMD_CUSTOM(xreset, "AT#XRESET", handle_at_reset); +static int handle_at_reset(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) +{ + if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { + return -EINVAL; } - return ret; + final_call(slm_reset); + return 0; } -/* Handles AT#XMODEMRESET command. */ -static int handle_at_modemreset(enum at_cmd_type type) +SLM_AT_CMD_CUSTOM(xmodemreset, "AT#XMODEMRESET", handle_at_modemreset); +static int handle_at_modemreset(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { - if (type != AT_CMD_TYPE_SET_COMMAND) { + if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { return -EINVAL; } /* The modem must be put in minimal function mode before being shut down. */ - modem_power_off(); + slm_power_off_modem(); unsigned int step = 1; int ret; @@ -257,12 +257,12 @@ static int handle_at_modemreset(enum at_cmd_type type) return 0; } -/* Handles AT#XUUID command. */ -static int handle_at_uuid(enum at_cmd_type type) +SLM_AT_CMD_CUSTOM(xuuid, "AT#XUUID", handle_at_uuid); +static int handle_at_uuid(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { int ret; - if (type != AT_CMD_TYPE_SET_COMMAND) { + if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { return -EINVAL; } @@ -278,15 +278,16 @@ static int handle_at_uuid(enum at_cmd_type type) return ret; } -/* Handles AT#XDATACTRL commands. */ -static int handle_at_datactrl(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xdatactrl, "AT#XDATACTRL", handle_at_datactrl); +static int handle_at_datactrl(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int ret = 0; uint16_t time_limit, time_limit_min; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - ret = at_params_unsigned_short_get(&slm_at_param_list, 1, &time_limit); + ret = at_params_unsigned_short_get(param_list, 1, &time_limit); if (ret) { return ret; } @@ -313,257 +314,62 @@ static int handle_at_datactrl(enum at_cmd_type cmd_type) return ret; } -int handle_at_clac(enum at_cmd_type cmd_type); - -/* TCP proxy commands */ -int handle_at_tcp_server(enum at_cmd_type cmd_type); -int handle_at_tcp_client(enum at_cmd_type cmd_type); -int handle_at_tcp_send(enum at_cmd_type cmd_type); -int handle_at_tcp_hangup(enum at_cmd_type cmd_type); - -/* UDP proxy commands */ -int handle_at_udp_server(enum at_cmd_type cmd_type); -int handle_at_udp_client(enum at_cmd_type cmd_type); -int handle_at_udp_send(enum at_cmd_type cmd_type); - -/* Socket-type TCPIP commands */ -int handle_at_socket(enum at_cmd_type cmd_type); -int handle_at_secure_socket(enum at_cmd_type cmd_type); -int handle_at_socket_select(enum at_cmd_type cmd_type); -int handle_at_socketopt(enum at_cmd_type cmd_type); -int handle_at_secure_socketopt(enum at_cmd_type cmd_type); -int handle_at_bind(enum at_cmd_type cmd_type); -int handle_at_connect(enum at_cmd_type cmd_type); -int handle_at_listen(enum at_cmd_type cmd_type); -int handle_at_accept(enum at_cmd_type cmd_type); -int handle_at_send(enum at_cmd_type cmd_type); -int handle_at_recv(enum at_cmd_type cmd_type); -int handle_at_sendto(enum at_cmd_type cmd_type); -int handle_at_recvfrom(enum at_cmd_type cmd_type); -int handle_at_poll(enum at_cmd_type cmd_type); -int handle_at_getaddrinfo(enum at_cmd_type cmd_type); - -#if defined(CONFIG_SLM_NATIVE_TLS) -int handle_at_xcmng(enum at_cmd_type cmd_type); -#endif - -/* ICMP commands */ -int handle_at_icmp_ping(enum at_cmd_type cmd_type); - -#if defined(CONFIG_SLM_SMS) -/* SMS commands */ -int handle_at_sms(enum at_cmd_type cmd_type); -#endif - -/* FOTA commands */ -int handle_at_fota(enum at_cmd_type cmd_type); - -#if defined(CONFIG_SLM_GNSS) -int handle_at_gps(enum at_cmd_type cmd_type); -int handle_at_gps_delete(enum at_cmd_type cmd_type); -#endif - -#if defined(CONFIG_SLM_FTPC) -int handle_at_ftp(enum at_cmd_type cmd_type); -#endif -#if defined(CONFIG_SLM_TFTPC) -int handle_at_tftp(enum at_cmd_type cmd_type); -#endif - -#if defined(CONFIG_SLM_MQTTC) -int handle_at_mqtt_config(enum at_cmd_type cmd_type); -int handle_at_mqtt_connect(enum at_cmd_type cmd_type); -int handle_at_mqtt_publish(enum at_cmd_type cmd_type); -int handle_at_mqtt_subscribe(enum at_cmd_type cmd_type); -int handle_at_mqtt_unsubscribe(enum at_cmd_type cmd_type); -#endif - -#if defined(CONFIG_SLM_HTTPC) -int handle_at_httpc_connect(enum at_cmd_type cmd_type); -int handle_at_httpc_request(enum at_cmd_type cmd_type); -#endif - -#if defined(CONFIG_SLM_TWI) -int handle_at_twi_list(enum at_cmd_type cmd_type); -int handle_at_twi_write(enum at_cmd_type cmd_type); -int handle_at_twi_read(enum at_cmd_type cmd_type); -int handle_at_twi_write_read(enum at_cmd_type cmd_type); -#endif - -#if defined(CONFIG_SLM_GPIO) -int handle_at_gpio_configure(enum at_cmd_type cmd_type); -int handle_at_gpio_operate(enum at_cmd_type cmd_type); -#endif - -static struct slm_at_cmd { - const char *string; - slm_at_handler_t handler; -} slm_at_cmd_list[] = { - /* Generic commands */ - {"AT#XSLMVER", handle_at_slmver}, - {"AT#XSLEEP", handle_at_sleep}, - {"AT#XSHUTDOWN", handle_at_shutdown}, - {"AT#XRESET", handle_at_reset}, - {"AT#XMODEMRESET", handle_at_modemreset}, - {"AT#XUUID", handle_at_uuid}, - {"AT#XCLAC", handle_at_clac}, - {"AT#XDATACTRL", handle_at_datactrl}, - - /* TCP proxy commands */ - {"AT#XTCPSVR", handle_at_tcp_server}, - {"AT#XTCPCLI", handle_at_tcp_client}, - {"AT#XTCPSEND", handle_at_tcp_send}, - {"AT#XTCPHANGUP", handle_at_tcp_hangup}, - - /* UDP proxy commands */ - {"AT#XUDPSVR", handle_at_udp_server}, - {"AT#XUDPCLI", handle_at_udp_client}, - {"AT#XUDPSEND", handle_at_udp_send}, - - /* Socket-type TCPIP commands */ - {"AT#XSOCKET", handle_at_socket}, - {"AT#XSSOCKET", handle_at_secure_socket}, - {"AT#XSOCKETSELECT", handle_at_socket_select}, - {"AT#XSOCKETOPT", handle_at_socketopt}, - {"AT#XSSOCKETOPT", handle_at_secure_socketopt}, - {"AT#XBIND", handle_at_bind}, - {"AT#XCONNECT", handle_at_connect}, - {"AT#XLISTEN", handle_at_listen}, - {"AT#XACCEPT", handle_at_accept}, - {"AT#XSEND", handle_at_send}, - {"AT#XRECV", handle_at_recv}, - {"AT#XSENDTO", handle_at_sendto}, - {"AT#XRECVFROM", handle_at_recvfrom}, - {"AT#XPOLL", handle_at_poll}, - {"AT#XGETADDRINFO", handle_at_getaddrinfo}, - -#if defined(CONFIG_SLM_NATIVE_TLS) - {"AT#XCMNG", handle_at_xcmng}, -#endif - /* ICMP commands */ - {"AT#XPING", handle_at_icmp_ping}, - -#if defined(CONFIG_SLM_SMS) - /* SMS commands */ - {"AT#XSMS", handle_at_sms}, -#endif - - /* FOTA commands */ - {"AT#XFOTA", handle_at_fota}, - -#if defined(CONFIG_SLM_NRF_CLOUD) - {"AT#XNRFCLOUD", handle_at_nrf_cloud}, -#if defined(CONFIG_NRF_CLOUD_LOCATION) - {"AT#XNRFCLOUDPOS", handle_at_nrf_cloud_pos}, -#endif -#endif - -#if defined(CONFIG_SLM_GNSS) - /* GNSS commands */ - {"AT#XGPS", handle_at_gps}, - {"AT#XGPSDEL", handle_at_gps_delete}, -#endif - -#if defined(CONFIG_SLM_FTPC) - /* FTP commands */ - {"AT#XFTP", handle_at_ftp}, -#endif -#if defined(CONFIG_SLM_TFTPC) - /* TFTP commands */ - {"AT#XTFTP", handle_at_tftp}, -#endif - -#if defined(CONFIG_SLM_MQTTC) - {"AT#XMQTTCFG", handle_at_mqtt_config}, - {"AT#XMQTTCON", handle_at_mqtt_connect}, - {"AT#XMQTTPUB", handle_at_mqtt_publish}, - {"AT#XMQTTSUB", handle_at_mqtt_subscribe}, - {"AT#XMQTTUNSUB", handle_at_mqtt_unsubscribe}, -#endif - -#if defined(CONFIG_SLM_HTTPC) - {"AT#XHTTPCCON", handle_at_httpc_connect}, - {"AT#XHTTPCREQ", handle_at_httpc_request}, -#endif - -#if defined(CONFIG_SLM_TWI) - {"AT#XTWILS", handle_at_twi_list}, - {"AT#XTWIW", handle_at_twi_write}, - {"AT#XTWIR", handle_at_twi_read}, - {"AT#XTWIWR", handle_at_twi_write_read}, -#endif - -#if defined(CONFIG_SLM_GPIO) - {"AT#XGPIOCFG", handle_at_gpio_configure}, - {"AT#XGPIO", handle_at_gpio_operate}, -#endif - -#if defined(CONFIG_SLM_CARRIER) - {"AT#XCARRIER", handle_at_carrier}, -#endif - -#if defined(CONFIG_LWM2M_CARRIER_SETTINGS) - {"AT#XCARRIERCFG", handle_at_carrier_cfg}, -#endif - -#if defined(CONFIG_SLM_PPP) - {"AT#XPPP", handle_at_ppp}, -#endif -}; - -/* Handles AT#XCLAC command. */ -int handle_at_clac(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xclac, "AT#XCLAC", handle_at_clac); +static int handle_at_clac(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { - int ret = -EINVAL; - - if (cmd_type == AT_CMD_TYPE_SET_COMMAND) { - int total = ARRAY_SIZE(slm_at_cmd_list); - - for (int i = 0; i < total; i++) { - rsp_send("%s\r\n", slm_at_cmd_list[i].string); - } - ret = 0; + if (cmd_type != AT_CMD_TYPE_SET_COMMAND) { + return -EINVAL; } - return ret; -} + /* Use AT_CMD_CUSTOM listing for extracting SLM AT commands. */ + extern struct nrf_modem_at_cmd_custom _nrf_modem_at_cmd_custom_list_start[]; + extern struct nrf_modem_at_cmd_custom _nrf_modem_at_cmd_custom_list_end[]; + size_t cmd_custom_count = _nrf_modem_at_cmd_custom_list_end - + _nrf_modem_at_cmd_custom_list_start; + size_t base_cmd_len[cmd_custom_count]; -int slm_at_parse(const char *cmd_str, size_t cmd_name_len) -{ - int ret = UNKNOWN_AT_COMMAND_RET; - int total = ARRAY_SIZE(slm_at_cmd_list); - - for (int i = 0; i < total; i++) { - const struct slm_at_cmd *const at_cmd = &slm_at_cmd_list[i]; - - /* For the match to happen the AT command names must be identical, - * which requires both names to have the same characters and the same length. - */ - if (!(!strncmp(cmd_str, at_cmd->string, cmd_name_len) - && at_cmd->string[cmd_name_len] == '\0')) { + memset(base_cmd_len, 0, cmd_custom_count * sizeof(size_t)); + rsp_send("\r\n"); + for (size_t i = 0; i < cmd_custom_count; i++) { + /* SLM at commands start with AT#X. */ + if (strncasecmp(_nrf_modem_at_cmd_custom_list_start[i].cmd, "AT#X", + strlen("AT#X"))) { continue; } + /* List commands without operations and list each command only once. */ + base_cmd_len[i] = strcspn(_nrf_modem_at_cmd_custom_list_start[i].cmd, "?="); + bool duplicate = false; + + for (size_t j = 0; j < i; j++) { + /* Compare length and command as we have AT commands such as + * AT#XSEND/AT#XSENDTO, AT#XFTP="whatever" + * and AT#XNRFCLOUD[=?]/AT#XNRFCLOUDPOS. + */ + if ((base_cmd_len[i] == base_cmd_len[j]) && + !strncasecmp(_nrf_modem_at_cmd_custom_list_start[i].cmd, + _nrf_modem_at_cmd_custom_list_start[j].cmd, + base_cmd_len[i])) { + duplicate = true; + break; + } + } - const enum at_cmd_type type = at_parser_cmd_type_get(cmd_str); - - at_params_list_clear(&slm_at_param_list); - ret = at_parser_params_from_str(cmd_str, NULL, &slm_at_param_list); - if (ret) { - LOG_ERR("Failed to parse AT command %d", ret); - return -EINVAL; + if (!duplicate) { + rsp_send("%.*s\r\n", base_cmd_len[i], + _nrf_modem_at_cmd_custom_list_start[i].cmd); } - ret = at_cmd->handler(type); - break; } - return ret; + return 0; } int slm_at_init(void) { int err; - k_work_init_delayable(&slm_work.sleep_work, go_sleep_wk); +#if POWER_PIN_IS_ENABLED + k_work_init_delayable(&sleep.work, go_sleep_wk); +#endif err = slm_at_tcp_proxy_init(); if (err) { @@ -580,13 +386,6 @@ int slm_at_init(void) LOG_ERR("TCPIP could not be initialized: %d", err); return -EFAULT; } -#if defined(CONFIG_SLM_NATIVE_TLS) - err = slm_at_cmng_init(); - if (err) { - LOG_ERR("TLS could not be initialized: %d", err); - return -EFAULT; - } -#endif err = slm_at_icmp_init(); if (err) { LOG_ERR("ICMP could not be initialized: %d", err); @@ -660,7 +459,16 @@ int slm_at_init(void) return -EFAULT; } #endif - +#if defined(CONFIG_SLM_CMUX) + slm_cmux_init(); +#endif +#if defined(CONFIG_SLM_PPP) + err = slm_ppp_init(); + if (err) { + LOG_ERR("PPP initialization failed. (%d)", err); + return err; + } +#endif return err; } @@ -680,12 +488,6 @@ void slm_at_uninit(void) if (err) { LOG_WRN("TCPIP could not be uninitialized: %d", err); } -#if defined(CONFIG_SLM_NATIVE_TLS) - err = slm_at_cmng_uninit(); - if (err) { - LOG_WRN("TLS could not be uninitialized: %d", err); - } -#endif err = slm_at_icmp_uninit(); if (err) { LOG_WRN("ICMP could not be uninitialized: %d", err); @@ -742,12 +544,6 @@ void slm_at_uninit(void) LOG_ERR("GPIO could not be uninit: %d", err); } #endif -#if defined(CONFIG_SLM_NRF52_DFU) - err = slm_at_dfu_uninit(); - if (err) { - LOG_ERR("DFU could not be uninitialized: %d", err); - } -#endif #if defined(CONFIG_SLM_CARRIER) err = slm_at_carrier_uninit(); if (err) { diff --git a/applications/serial_lte_modem/src/slm_at_fota.c b/applications/serial_lte_modem/src/slm_at_fota.c index ef183c61cc8..1df8a9a2939 100644 --- a/applications/serial_lte_modem/src/slm_at_fota.c +++ b/applications/serial_lte_modem/src/slm_at_fota.c @@ -292,8 +292,9 @@ static void fota_dl_handler(const struct fota_download_evt *evt) } } -/* Handles AT#XFOTA commands. */ -int handle_at_fota(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xfota, "AT#XFOTA", handle_at_fota); +static int handle_at_fota(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; @@ -303,7 +304,7 @@ int handle_at_fota(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err < 0) { return err; } @@ -322,12 +323,12 @@ int handle_at_fota(enum at_cmd_type cmd_type) sec_tag_t sec_tag = INVALID_SEC_TAG; enum dfu_target_image_type type; - err = util_string_get(&slm_at_param_list, 2, uri, &size); + err = util_string_get(param_list, 2, uri, &size); if (err) { return err; } - if (at_params_valid_count_get(&slm_at_param_list) > 3) { - at_params_unsigned_int_get(&slm_at_param_list, 3, &sec_tag); + if (param_count > 3) { + at_params_unsigned_int_get(param_list, 3, &sec_tag); } if (op == SLM_FOTA_START_APP) { type = DFU_TARGET_IMAGE_TYPE_MCUBOOT; @@ -356,8 +357,8 @@ int handle_at_fota(enum at_cmd_type cmd_type) else { type = DFU_TARGET_IMAGE_TYPE_MODEM_DELTA; } - if (at_params_valid_count_get(&slm_at_param_list) > 4) { - at_params_unsigned_short_get(&slm_at_param_list, 4, &pdn_id); + if (param_count > 4) { + at_params_unsigned_short_get(param_list, 4, &pdn_id); err = do_fota_start(op, uri, sec_tag, pdn_id, type); } else { err = do_fota_start(op, uri, sec_tag, 0, type); diff --git a/applications/serial_lte_modem/src/slm_at_host.c b/applications/serial_lte_modem/src/slm_at_host.c index 84e3a47f60f..13ee950070a 100644 --- a/applications/serial_lte_modem/src/slm_at_host.c +++ b/applications/serial_lte_modem/src/slm_at_host.c @@ -4,29 +4,32 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#include -#include -#include -#include -#include -#include #include "slm_at_host.h" #include "slm_at_fota.h" #include "slm_uart_handler.h" +#include "slm_util.h" #if defined(CONFIG_SLM_PPP) #include "slm_ppp.h" #endif +#include +#include +#include +#include +#include #include +#include +#include LOG_MODULE_REGISTER(slm_at_host, CONFIG_SLM_LOG_LEVEL); +#define SLM_SYNC_STR "Ready\r\n" #define OK_STR "\r\nOK\r\n" #define ERROR_STR "\r\nERROR\r\n" -#define FATAL_STR "FATAL ERROR\r\n" #define CRLF_STR "\r\n" #define CR '\r' #define LF '\n' +#define HEXDUMP_LIMIT 16 -const char *slm_quit_str = CONFIG_SLM_DATAMODE_TERMINATOR; +static const char *const slm_quit_str = CONFIG_SLM_DATAMODE_TERMINATOR; /* Operation mode variables */ enum slm_operation_mode { @@ -34,14 +37,15 @@ enum slm_operation_mode { SLM_DATA_MODE, /* Raw data sending */ SLM_NULL_MODE /* Discard incoming until next command */ }; +static struct slm_at_backend at_backend; static enum slm_operation_mode at_mode; static slm_datamode_handler_t datamode_handler; static int datamode_handler_result; uint16_t slm_datamode_time_limit; /* Send trigger by time in data mode */ K_MUTEX_DEFINE(mutex_mode); /* Protects the operation mode variables. */ -struct at_param_list slm_at_param_list; -uint8_t slm_at_buf[SLM_AT_MAX_CMD_LEN]; +static struct at_param_list at_host_param_list; +uint8_t slm_at_buf[SLM_AT_MAX_CMD_LEN + 1]; uint8_t slm_data_buf[SLM_MAX_MESSAGE_SIZE]; RING_BUF_DECLARE(data_rb, CONFIG_SLM_DATAMODE_BUF_SIZE); @@ -425,17 +429,87 @@ static void format_final_result(char *buf, size_t buf_len, size_t buf_max_len) } } } +static void restore_at_backend(void) +{ + const int err = at_backend.start(); + + if (err) { + LOG_ERR("Failed to restore AT backend. (%d) Resetting.", err); + slm_reset(); + } +} + +static int stop_at_backend(void) +{ + const int err = at_backend.stop(); + + if (!err) { + /* Wait for UART disabling to complete. */ + k_sleep(K_MSEC(100)); + } + return err; +} + +int slm_at_set_backend(const struct slm_at_backend new_backend) +{ + const struct slm_at_backend old_backend = at_backend; + int ret; + + if (old_backend.start) { + ret = stop_at_backend(); + if (ret) { + LOG_ERR("Failed to stop previous AT backend. (%d)", ret); + return ret; + } + } + + at_backend = new_backend; + ret = new_backend.start(); + if (ret) { + LOG_ERR("Failed to start AT backend. (%d)", ret); + stop_at_backend(); + + at_backend = old_backend; + restore_at_backend(); + } + + return ret; +} -static size_t cmd_name_toupper(char *cmd, size_t cmd_len) +static int slm_at_send_indicate(const uint8_t *data, size_t len, + bool print_full_debug, bool indicate) { - size_t i; + int ret; - /* Set/test command names are delimited by '=', read by '?'. */ - for (i = 0; i != cmd_len && cmd[i] != '=' && cmd[i] != '?'; ++i) { + if (k_is_in_isr()) { + LOG_ERR("FIXME: Attempt to send AT response (of size %u) in ISR.", len); + return -EINTR; + } + + if (indicate) { + enum pm_device_state state = PM_DEVICE_STATE_OFF; - cmd[i] = toupper(cmd[i]); + pm_device_state_get(slm_uart_dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + slm_indicate(); + } } - return i; + + ret = at_backend.send(data, len); + if (!ret) { + LOG_HEXDUMP_DBG(data, print_full_debug ? len : MIN(HEXDUMP_LIMIT, len), "TX"); + } + return ret; +} + +int slm_at_send(const uint8_t *data, size_t len) +{ + return slm_at_send_indicate(data, len, true, false); +} + +int slm_at_send_str(const char *str) +{ + return slm_at_send(str, strlen(str)); } static void cmd_send(uint8_t *buf, size_t cmd_length, size_t buf_size) @@ -464,21 +538,11 @@ static void cmd_send(uint8_t *buf, size_t cmd_length, size_t buf_size) return; } - const size_t cmd_name_len = cmd_name_toupper(at_cmd, cmd_length); - - err = slm_at_parse(at_cmd, cmd_name_len); - if (err == 0) { - rsp_send_ok(); - return; - } else if (err != UNKNOWN_AT_COMMAND_RET) { - LOG_ERR("AT command error: %d (%s)", err, strerror(-err)); - rsp_send_error(); - return; - } - /* Send to modem, reserve space for CRLF in response buffer */ err = nrf_modem_at_cmd(buf + strlen(CRLF_STR), buf_size - strlen(CRLF_STR), "%s", at_cmd); - if (err < 0) { + if (err == -SILENT_AT_COMMAND_RET) { + return; + } else if (err < 0) { LOG_ERR("AT command failed: %d", err); rsp_send_error(); return; @@ -492,8 +556,8 @@ static void cmd_send(uint8_t *buf, size_t cmd_length, size_t buf_size) buf[0] = CR; buf[1] = LF; if (strlen(buf) > strlen(CRLF_STR)) { - format_final_result((char *)buf, strlen(buf), buf_size); - err = slm_uart_tx_write(buf, strlen(buf), true, false); + format_final_result(buf, strlen(buf), buf_size); + err = slm_at_send_str(buf); if (err) { LOG_ERR("AT command response failed: %d", err); } @@ -614,37 +678,29 @@ static size_t null_handler(const uint8_t *buf, const size_t len) return processed; } -static void rx_handler_callback(const uint8_t *buf, size_t len) +void slm_at_receive(const uint8_t *buf, size_t len) { - enum slm_operation_mode mode; size_t ret = 0; k_timer_stop(&inactivity_timer); while (len > 0) { - mode = get_slm_mode(); - - if (mode == SLM_AT_COMMAND_MODE) { + switch (get_slm_mode()) { + case SLM_AT_COMMAND_MODE: ret = cmd_rx_handler(buf, len); - } else if (mode == SLM_DATA_MODE) { + break; + case SLM_DATA_MODE: ret = raw_rx_handler(buf, len); - } else if (mode == SLM_NULL_MODE) { + break; + case SLM_NULL_MODE: ret = null_handler(buf, len); - } else { - LOG_ERR("Internal error: Unknown SLM mode."); - (void)slm_uart_tx_write(FATAL_STR, sizeof(FATAL_STR) - 1, true, false); break; } - if (len >= ret) { - buf += ret; - len -= ret; - } else { - LOG_ERR("Internal error: Command overflow."); - (void)slm_uart_tx_write(FATAL_STR, sizeof(FATAL_STR) - 1, true, false); - break; - } + assert(ret <= len); + buf += ret; + len -= ret; } /* start inactivity timer in datamode */ @@ -666,45 +722,44 @@ static void notification_handler(const char *notification) return; } #endif - (void)slm_uart_tx_write(CRLF_STR, strlen(CRLF_STR), true, true); - (void)slm_uart_tx_write(notification, strlen(notification), true, false); + slm_at_send_indicate(CRLF_STR, strlen(CRLF_STR), true, true); + slm_at_send_str(notification); } } void rsp_send_ok(void) { - (void)slm_uart_tx_write(OK_STR, sizeof(OK_STR) - 1, true, false); + slm_at_send_str(OK_STR); } void rsp_send_error(void) { - (void)slm_uart_tx_write(ERROR_STR, sizeof(ERROR_STR) - 1, true, false); + slm_at_send_str(ERROR_STR); } void rsp_send(const char *fmt, ...) { static K_MUTEX_DEFINE(mutex_rsp_buf); static char rsp_buf[SLM_AT_MAX_RSP_LEN]; + int rsp_len; - if (!slm_uart_can_context_send(fmt, strlen(fmt))) { - return; - } k_mutex_lock(&mutex_rsp_buf, K_FOREVER); va_list arg_ptr; va_start(arg_ptr, fmt); - vsnprintf(rsp_buf, sizeof(rsp_buf), fmt, arg_ptr); + rsp_len = vsnprintf(rsp_buf, sizeof(rsp_buf), fmt, arg_ptr); + rsp_len = MIN(rsp_len, sizeof(rsp_buf) - 1); va_end(arg_ptr); - (void)slm_uart_tx_write(rsp_buf, strlen(rsp_buf), true, false); + slm_at_send(rsp_buf, rsp_len); k_mutex_unlock(&mutex_rsp_buf); } void data_send(const uint8_t *data, size_t len) { - (void)slm_uart_tx_write(data, len, false, true); + slm_at_send_indicate(data, len, false, true); } int enter_datamode(slm_datamode_handler_t handler) @@ -792,12 +847,48 @@ bool verify_datamode_control(uint16_t time_limit, uint16_t *min_time_limit) return true; } +int slm_get_at_param_list(const char *at_cmd, struct at_param_list **list) +{ + int err; + + *list = &at_host_param_list; + + err = at_parser_params_from_str(at_cmd, NULL, *list); + if (err) { + LOG_ERR("AT command parsing failed: %d", err); + } + + return err; +} + +int slm_at_cb_wrapper(char *buf, size_t len, char *at_cmd, slm_at_callback *cb) +{ + int err; + struct at_param_list *list = NULL; + + assert(cb); + + err = slm_get_at_param_list(at_cmd, &list); + if (err) { + return err; + } + err = cb(at_parser_cmd_type_get(at_cmd), list, at_params_valid_count_get(list)); + if (!err) { + err = at_cmd_custom_respond(buf, len, "OK\r\n"); + if (err) { + LOG_ERR("Failed to set OK response: %d", err); + } + } + + return err; +} + int slm_at_host_init(void) { int err; /* Initialize AT Parser */ - err = at_params_list_init(&slm_at_param_list, CONFIG_SLM_AT_MAX_PARAM); + err = at_params_list_init(&at_host_param_list, CONFIG_SLM_AT_MAX_PARAM); if (err) { LOG_ERR("Failed to init AT Parser: %d", err); return err; @@ -814,17 +905,14 @@ int slm_at_host_init(void) return -EFAULT; } -#if defined(CONFIG_SLM_PPP) - err = slm_ppp_init(); + k_work_init(&raw_send_scheduled_work, raw_send_scheduled); + + err = slm_uart_handler_enable(); if (err) { - LOG_ERR("PPP initialization failed (%d).", err); return err; } -#endif - - k_work_init(&raw_send_scheduled_work, raw_send_scheduled); - err = slm_uart_handler_init(rx_handler_callback); + err = slm_at_send_str(SLM_SYNC_STR); if (err) { return err; } @@ -838,6 +926,54 @@ int slm_at_host_init(void) return 0; } +static int at_host_power_off(bool shutting_down) +{ + int err = stop_at_backend(); + + if (!err || shutting_down) { + + /* Power off UART module */ + err = pm_device_action_run(slm_uart_dev, PM_DEVICE_ACTION_SUSPEND); + if (err == -EALREADY) { + err = 0; + } + if (err) { + LOG_WRN("Failed to suspend UART. (%d)", err); + if (!shutting_down) { + restore_at_backend(); + } + } + } + + return err; +} + +int slm_at_host_power_off(void) +{ + const int err = at_host_power_off(false); + + /* Write sync str to buffer so it is sent first when resuming. */ + slm_at_send_str(SLM_SYNC_STR); + + return err; +} + +int slm_at_host_power_on(void) +{ + const int err = pm_device_action_run(slm_uart_dev, PM_DEVICE_ACTION_RESUME); + + if (err && err != -EALREADY) { + LOG_ERR("Failed to resume UART. (%d)", err); + return err; + } + + /* Wait for UART enabling to complete. */ + k_sleep(K_MSEC(100)); + + restore_at_backend(); + return 0; +} + void slm_at_host_uninit(void) { k_mutex_lock(&mutex_mode, K_FOREVER); @@ -849,11 +985,10 @@ void slm_at_host_uninit(void) slm_at_uninit(); - /* Power off UART module */ - slm_uart_handler_uninit(); + at_host_power_off(true); /* Un-initialize AT Parser */ - at_params_list_free(&slm_at_param_list); + at_params_list_free(&at_host_param_list); LOG_DBG("at_host uninit done"); } diff --git a/applications/serial_lte_modem/src/slm_at_host.h b/applications/serial_lte_modem/src/slm_at_host.h index a3068b0f316..e315455bf5d 100644 --- a/applications/serial_lte_modem/src/slm_at_host.h +++ b/applications/serial_lte_modem/src/slm_at_host.h @@ -7,7 +7,7 @@ #ifndef SLM_AT_HOST_ #define SLM_AT_HOST_ -/**@file slm_at_host.h +/** @file slm_at_host.h * * @brief AT host for serial LTE modem * @{ @@ -17,25 +17,28 @@ #include #include #include +#include #include #include "slm_defines.h" -#define SLM_DATAMODE_FLAGS_NONE 0 -#define SLM_DATAMODE_FLAGS_MORE_DATA 1 << 0 +/* This delay is necessary to send AT responses at low baud rates. */ +#define SLM_UART_RESPONSE_DELAY K_MSEC(50) + +#define SLM_DATAMODE_FLAGS_NONE 0 +#define SLM_DATAMODE_FLAGS_MORE_DATA (1 << 0) -extern struct at_param_list slm_at_param_list; /* For AT parser. */ extern uint8_t slm_data_buf[SLM_MAX_MESSAGE_SIZE]; /* For socket data. */ -extern uint8_t slm_at_buf[SLM_AT_MAX_CMD_LEN]; /* AT command buffer. */ +extern uint8_t slm_at_buf[SLM_AT_MAX_CMD_LEN + 1]; /* AT command buffer. */ extern uint16_t slm_datamode_time_limit; /* Send trigger by time in data mode. */ -/**@brief Operations in datamode. */ +/** @brief Operations in data mode. */ enum slm_datamode_operation { DATAMODE_SEND, /* Send data in datamode */ DATAMODE_EXIT /* Exit data mode */ }; -/**@brief Data mode sending handler type. +/** @brief Data mode sending handler type. * * @retval 0 means all data is sent successfully. * Positive value means the actual size of bytes that has been sent. @@ -43,6 +46,28 @@ enum slm_datamode_operation { */ typedef int (*slm_datamode_handler_t)(uint8_t op, const uint8_t *data, int len, uint8_t flags); +/* All the AT backend API functions return 0 on success. */ +struct slm_at_backend { + int (*start)(void); + int (*send)(const uint8_t *data, size_t len); + int (*stop)(void); +}; +/** @retval 0 on success (the new backend is successfully started). */ +int slm_at_set_backend(struct slm_at_backend backend); + +/** + * @brief Sends the given data via the current AT backend. + * + * @retval 0 on success. + */ +int slm_at_send(const uint8_t *data, size_t len); + +/** @brief Identical to slm_at_send(str, strlen(str)). */ +int slm_at_send_str(const char *str); + +/** @brief Processes received AT bytes. */ +void slm_at_receive(const uint8_t *data, size_t len); + /** * @brief Initialize AT host for serial LTE modem * @@ -52,14 +77,19 @@ typedef int (*slm_datamode_handler_t)(uint8_t op, const uint8_t *data, int len, int slm_at_host_init(void); /** - * @brief Uninitialize AT host for serial LTE modem + * @brief Turns the current AT backend and UART power off. + * + * @retval 0 on success, or a (negative) error code. */ -void slm_at_host_uninit(void); +int slm_at_host_power_off(void); + +/** @brief Counterpart to @c slm_at_host_power_off(). */ +int slm_at_host_power_on(void); /** - * @brief Runs the SLM-proprietary @c at_cmd if it is one. + * @brief Uninitialize AT host for serial LTE modem */ -int slm_at_parse(const char *cmd_str, size_t cmd_name_len); +void slm_at_host_uninit(void); /** * @brief Send AT command response @@ -116,6 +146,54 @@ bool in_datamode(void); * false If not in data mode. */ bool exit_datamode_handler(int result); + +/** + * @brief Get parameter list from AT command. + * + * @param at_cmd AT command. + * @param list Pointer to the parameter list. + * + * @retval 0 on success. Otherwise, a (negative) error code is returned. + */ +int slm_get_at_param_list(const char *at_cmd, struct at_param_list **list); + +/** @brief SLM AT command callback type. */ +typedef int slm_at_callback(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count); + +/** + * @brief Generic wrapper for a custom SLM AT command callback. + * + * This will call the AT command handler callback, which is declared with SLM_AT_CMD_CUSTOM. + * + * @param buf Response buffer. + * @param len Response buffer size. + * @param at_cmd AT command. + * @param cb AT command callback. + + * @retval 0 on success. + */ +int slm_at_cb_wrapper(char *buf, size_t len, char *at_cmd, slm_at_callback cb); + +/** + * @brief Define a wrapper for a SLM custom AT command callback. + * + * Wrapper will call the generic wrapper, which will call the actual AT command handler. + * + * @param entry The entry name. + * @param _filter The (partial) AT command on which the callback should trigger. + * @param _callback The AT command handler callback. + * + */ +#define SLM_AT_CMD_CUSTOM(entry, _filter, _callback) \ + static int _callback(enum at_cmd_type cmd_type, const struct at_param_list *list, \ + uint32_t); \ + static int _callback##_wrapper_##entry(char *buf, size_t len, char *at_cmd) \ + { \ + return slm_at_cb_wrapper(buf, len, at_cmd, _callback); \ + } \ + AT_CMD_CUSTOM(entry, _filter, _callback##_wrapper_##entry); + /** @} */ #endif /* SLM_AT_HOST_ */ diff --git a/applications/serial_lte_modem/src/slm_at_icmp.c b/applications/serial_lte_modem/src/slm_at_icmp.c index 4fccd203a87..caed9066064 100644 --- a/applications/serial_lte_modem/src/slm_at_icmp.c +++ b/applications/serial_lte_modem/src/slm_at_icmp.c @@ -517,8 +517,9 @@ static int ping_test_handler(const char *target) return 0; } -/* Handles AT#XPING command. */ -int handle_at_icmp_ping(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xping, "AT#XPING", handle_at_icmp_ping); +static int handle_at_icmp_ping(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; char target[SLM_MAX_URL]; @@ -526,36 +527,35 @@ int handle_at_icmp_ping(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = util_string_get(&slm_at_param_list, 1, target, &size); + err = util_string_get(param_list, 1, target, &size); if (err < 0) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &ping_argv.len); + err = at_params_unsigned_short_get(param_list, 2, &ping_argv.len); if (err < 0) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &ping_argv.waitms); + err = at_params_unsigned_short_get(param_list, 3, &ping_argv.waitms); if (err < 0) { return err; } ping_argv.count = 1; /* default 1 */ - if (at_params_valid_count_get(&slm_at_param_list) > 4) { - err = at_params_unsigned_short_get(&slm_at_param_list, 4, &ping_argv.count); + if (param_count > 4) { + err = at_params_unsigned_short_get(param_list, 4, &ping_argv.count); if (err < 0) { return err; }; } ping_argv.interval = 1000; /* default 1s */ - if (at_params_valid_count_get(&slm_at_param_list) > 5) { - err = at_params_unsigned_short_get( - &slm_at_param_list, 5, &ping_argv.interval); + if (param_count > 5) { + err = at_params_unsigned_short_get(param_list, 5, &ping_argv.interval); if (err < 0) { return err; }; } ping_argv.pdn = 0; /* default 0 primary PDN */ - if (at_params_valid_count_get(&slm_at_param_list) > 6) { - err = at_params_unsigned_short_get(&slm_at_param_list, 6, &ping_argv.pdn); + if (param_count > 6) { + err = at_params_unsigned_short_get(param_list, 6, &ping_argv.pdn); if (err < 0) { return err; }; diff --git a/applications/serial_lte_modem/src/slm_at_sms.c b/applications/serial_lte_modem/src/slm_at_sms.c index bb73289ff4c..9e2c40992b0 100644 --- a/applications/serial_lte_modem/src/slm_at_sms.c +++ b/applications/serial_lte_modem/src/slm_at_sms.c @@ -171,16 +171,16 @@ static int do_sms_send(const char *number, const char *message) return err; } - -/* Handles AT#XSMS commands. */ -int handle_at_sms(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsms, "AT#XSMS", handle_at_sms); +static int handle_at_sms(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint16_t op; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -194,12 +194,12 @@ int handle_at_sms(enum at_cmd_type cmd_type) int size; size = SMS_MAX_ADDRESS_LEN_CHARS + 1; - err = util_string_get(&slm_at_param_list, 2, number, &size); + err = util_string_get(param_list, 2, number, &size); if (err) { return err; } size = MAX_CONCATENATED_MESSAGE * SMS_MAX_PAYLOAD_LEN_CHARS; - err = util_string_get(&slm_at_param_list, 3, message, &size); + err = util_string_get(param_list, 3, message, &size); if (err) { return err; } diff --git a/applications/serial_lte_modem/src/slm_at_socket.c b/applications/serial_lte_modem/src/slm_at_socket.c index 3846c380fd3..792cfcd493b 100644 --- a/applications/serial_lte_modem/src/slm_at_socket.c +++ b/applications/serial_lte_modem/src/slm_at_socket.c @@ -7,13 +7,17 @@ #include #include #include +#include #include #include #include #include "slm_util.h" #include "slm_at_host.h" #include "slm_at_socket.h" +#include "slm_sockopt.h" +#if defined(CONFIG_SLM_NATIVE_TLS) #include "slm_native_tls.h" +#endif LOG_MODULE_REGISTER(slm_sock, CONFIG_SLM_LOG_LEVEL); @@ -62,8 +66,10 @@ static struct pollfd fds[SLM_MAX_SOCKET_COUNT]; static struct slm_socket sock; /* forward declarations */ -#define SOCKET_SEND_TMO_SEC 30 +#define SOCKET_SEND_TMO_SEC 30 static int socket_poll(int sock_fd, int event, int timeout); +static int handle_at_sendto(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count); static int socket_ranking; @@ -143,69 +149,91 @@ static int do_socket_open(void) } sock.fd = ret; + struct timeval tmo = {.tv_sec = SOCKET_SEND_TMO_SEC}; + + ret = setsockopt(sock.fd, SOL_SOCKET, SO_SNDTIMEO, &tmo, sizeof(tmo)); + if (ret) { + LOG_ERR("setsockopt(%d) error: %d", SO_SNDTIMEO, -errno); + ret = -errno; + goto error; + } + /* Explicitly bind to secondary PDP context if required */ ret = bind_to_pdn(sock.cid); if (ret) { - close(sock.fd); - return ret; + goto error; } sock.ranking = socket_ranking++; ret = find_avail_socket(); if (ret < 0) { - return ret; + goto error; } socks[ret] = sock; rsp_send("\r\n#XSOCKET: %d,%d,%d\r\n", sock.fd, sock.type, proto); return 0; + +error: + close(sock.fd); + sock.fd = INVALID_SOCKET; + return ret; } static int do_secure_socket_open(int peer_verify) { int ret = 0; - int proto = IPPROTO_TLS_1_2; + int proto = sock.type == SOCK_STREAM ? IPPROTO_TLS_1_2 : IPPROTO_DTLS_1_2; - if (sock.type == SOCK_STREAM) { -#if defined(CONFIG_SLM_NATIVE_TLS) - ret = socket(sock.family, SOCK_STREAM | SOCK_NATIVE_TLS, IPPROTO_TLS_1_2); -#else - ret = socket(sock.family, SOCK_STREAM, IPPROTO_TLS_1_2); -#endif - } else if (sock.type == SOCK_DGRAM) { - ret = socket(sock.family, SOCK_DGRAM, IPPROTO_DTLS_1_2); - proto = IPPROTO_DTLS_1_2; - } else { + if (sock.type != SOCK_STREAM && sock.type != SOCK_DGRAM) { LOG_ERR("socket type %d not supported", sock.type); return -ENOTSUP; } + + ret = socket(sock.family, sock.type, proto); if (ret < 0) { LOG_ERR("socket() error: %d", -errno); return -errno; } sock.fd = ret; - /* Explicitly bind to secondary PDP context if required */ - ret = bind_to_pdn(sock.cid); - if (ret) { - close(sock.fd); - return ret; - } - sec_tag_t sec_tag_list[1] = { sock.sec_tag }; #if defined(CONFIG_SLM_NATIVE_TLS) if (sock.type == SOCK_STREAM) { - ret = slm_tls_loadcrdl(sock.sec_tag); + ret = slm_native_tls_load_credentials(sock.sec_tag); if (ret < 0) { - LOG_ERR("Fail to load credential: %d", ret); - goto error_exit; + LOG_ERR("Failed to load sec tag: %d (%d)", sock.sec_tag, ret); + goto error; + } + int tls_native = 1; + + /* Must be the first socket option to set. */ + ret = setsockopt(sock.fd, SOL_TLS, TLS_NATIVE, &tls_native, sizeof(tls_native)); + if (ret) { + goto error; } } #endif + struct timeval tmo = {.tv_sec = SOCKET_SEND_TMO_SEC}; + + ret = setsockopt(sock.fd, SOL_SOCKET, SO_SNDTIMEO, &tmo, sizeof(tmo)); + if (ret) { + LOG_ERR("setsockopt(%d) error: %d", SO_SNDTIMEO, -errno); + ret = -errno; + goto error; + } + + /* Explicitly bind to secondary PDP context if required */ + ret = bind_to_pdn(sock.cid); + if (ret) { + goto error; + } + sec_tag_t sec_tag_list[1] = { sock.sec_tag }; + ret = setsockopt(sock.fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, sizeof(sec_tag_t)); if (ret) { LOG_ERR("setsockopt(TLS_SEC_TAG_LIST) error: %d", -errno); ret = -errno; - goto error_exit; + goto error; } /* Set up (D)TLS peer verification */ @@ -213,7 +241,7 @@ static int do_secure_socket_open(int peer_verify) if (ret) { LOG_ERR("setsockopt(TLS_PEER_VERIFY) error: %d", errno); ret = -errno; - goto error_exit; + goto error; } /* Set up (D)TLS server role if applicable */ if (sock.role == AT_SOCKET_ROLE_SERVER) { @@ -223,29 +251,23 @@ static int do_secure_socket_open(int peer_verify) if (ret) { LOG_ERR("setsockopt(TLS_DTLS_ROLE) error: %d", -errno); ret = -errno; - goto error_exit; + goto error; } } sock.ranking = socket_ranking++; ret = find_avail_socket(); if (ret < 0) { - return ret; + goto error; } socks[ret] = sock; rsp_send("\r\n#XSSOCKET: %d,%d,%d\r\n", sock.fd, sock.type, proto); return 0; -error_exit: -#if defined(CONFIG_SLM_NATIVE_TLS) - if (sock.type == SOCK_STREAM && sock.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(sock.sec_tag); - sock.sec_tag = INVALID_SEC_TAG; - } -#endif +error: close(sock.fd); - INIT_SOCKET(sock); + sock.fd = INVALID_SOCKET; return ret; } @@ -257,15 +279,6 @@ static int do_socket_close(void) return 0; } -#if defined(CONFIG_SLM_NATIVE_TLS) - if (sock.type == SOCK_STREAM && sock.sec_tag != INVALID_SEC_TAG) { - ret = slm_tls_unloadcrdl(sock.sec_tag); - if (ret < 0) { - LOG_WRN("Fail to unload credential: %d", ret); - } - sock.sec_tag = INVALID_SEC_TAG; - } -#endif if (sock.fd_peer != INVALID_SOCKET) { ret = close(sock.fd_peer); if (ret) { @@ -308,208 +321,239 @@ static int do_socket_close(void) return ret; } -static int do_socketopt_set(int option, int value) +static int at_sockopt_to_sockopt(enum at_sockopt at_option, int *level, int *option) { - int ret = 0; - - switch (option) { - case SO_BINDTOPDN: - case SO_REUSEADDR: - ret = setsockopt(sock.fd, SOL_SOCKET, option, &value, sizeof(int)); + switch (at_option) { + case AT_SO_REUSEADDR: + *level = SOL_SOCKET; + *option = SO_REUSEADDR; break; - - case SO_RCVTIMEO: - case SO_SNDTIMEO: { - struct timeval tmo = { .tv_sec = value }; - socklen_t len = sizeof(struct timeval); - - ret = setsockopt(sock.fd, SOL_SOCKET, option, &tmo, len); - } break; - - /** NCS extended socket options */ - case SO_SILENCE_ALL: - ret = setsockopt(sock.fd, IPPROTO_ALL, option, &value, sizeof(int)); + case AT_SO_RCVTIMEO: + *level = SOL_SOCKET; + *option = SO_RCVTIMEO; break; - case SO_IP_ECHO_REPLY: - ret = setsockopt(sock.fd, IPPROTO_IP, option, &value, sizeof(int)); + case AT_SO_SNDTIMEO: + *level = SOL_SOCKET; + *option = SO_SNDTIMEO; break; - case SO_IPV6_ECHO_REPLY: - ret = setsockopt(sock.fd, IPPROTO_IPV6, option, &value, sizeof(int)); + case AT_SO_SILENCE_ALL: + *level = IPPROTO_ALL; + *option = SO_SILENCE_ALL; break; - case SO_TCP_SRV_SESSTIMEO: - ret = setsockopt(sock.fd, IPPROTO_TCP, option, &value, sizeof(int)); + case AT_SO_IP_ECHO_REPLY: + *level = IPPROTO_IP; + *option = SO_IP_ECHO_REPLY; break; - - /* RAI-related */ - case SO_RAI_LAST: - case SO_RAI_NO_DATA: - case SO_RAI_ONE_RESP: - case SO_RAI_ONGOING: - case SO_RAI_WAIT_MORE: - ret = setsockopt(sock.fd, SOL_SOCKET, option, NULL, 0); + case AT_SO_IPV6_ECHO_REPLY: + *level = IPPROTO_IPV6; + *option = SO_IPV6_ECHO_REPLY; break; - - default: - ret = -ENOTSUP; - LOG_WRN("Unsupported option: %d", option); + case AT_SO_BINDTOPDN: + *level = SOL_SOCKET; + *option = SO_BINDTOPDN; + break; + case AT_SO_RAI: + *level = SOL_SOCKET; + *option = SO_RAI; + break; + case AT_SO_RAI_NO_DATA: + *level = SOL_SOCKET; + *option = SO_RAI_NO_DATA; + break; + case AT_SO_RAI_LAST: + *level = SOL_SOCKET; + *option = SO_RAI_LAST; + break; + case AT_SO_RAI_ONE_RESP: + *level = SOL_SOCKET; + *option = SO_RAI_ONE_RESP; + break; + case AT_SO_RAI_ONGOING: + *level = SOL_SOCKET; + *option = SO_RAI_ONGOING; + break; + case AT_SO_RAI_WAIT_MORE: + *level = SOL_SOCKET; + *option = SO_RAI_WAIT_MORE; + break; + case AT_SO_TCP_SRV_SESSTIMEO: + *level = IPPROTO_TCP; + *option = SO_TCP_SRV_SESSTIMEO; break; - } - if (ret && ret != -ENOTSUP) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); + default: + LOG_WRN("Unsupported option: %d", at_option); + return -ENOTSUP; } - return ret; + return 0; } -static int do_sockopt_get_int(int level, int option) +static int sockopt_set(enum at_sockopt at_option, int at_value) { - int ret; - int value; - socklen_t len = sizeof(int); + int ret, level, option; + void *value = &at_value; + socklen_t len = sizeof(at_value); + struct timeval tmo; - ret = getsockopt(sock.fd, level, option, &value, &len); - if (ret == 0) { - rsp_send("\r\n#XSOCKETOPT: %d\r\n", value); + ret = at_sockopt_to_sockopt(at_option, &level, &option); + if (ret) { + return ret; + } + + /* Options with special handling. */ + if (level == SOL_SOCKET && (option == SO_RCVTIMEO || option == SO_SNDTIMEO)) { + tmo.tv_sec = at_value; + value = &tmo; + len = sizeof(tmo); + } else if (level == SOL_SOCKET && (option == SO_RAI_LAST || option == SO_RAI_NO_DATA || + option == SO_RAI_ONE_RESP || option == SO_RAI_ONGOING || + option == SO_RAI_WAIT_MORE)) { + value = NULL; + len = 0; + } + + ret = setsockopt(sock.fd, level, option, value, len); + if (ret) { + LOG_ERR("setsockopt(%d,%d) error: %d", level, option, -errno); } return ret; } -static int do_socketopt_get(int option) +static int sockopt_get(enum at_sockopt at_option) { - int ret = 0; + int ret, value, level, option; + socklen_t len = sizeof(int); - switch (option) { - case SO_SILENCE_ALL: - ret = do_sockopt_get_int(IPPROTO_ALL, option); - break; - case SO_IP_ECHO_REPLY: - ret = do_sockopt_get_int(IPPROTO_IP, option); - break; - case SO_IPV6_ECHO_REPLY: - ret = do_sockopt_get_int(IPPROTO_IPV6, option); - break; - case SO_TCP_SRV_SESSTIMEO: - ret = do_sockopt_get_int(IPPROTO_TCP, option); - break; - case SO_ERROR: - ret = do_sockopt_get_int(SOL_SOCKET, option); - break; + ret = at_sockopt_to_sockopt(at_option, &level, &option); + if (ret) { + return ret; + } - case SO_RCVTIMEO: - case SO_SNDTIMEO: { + /* Options with special handling. */ + if (level == SOL_SOCKET && (option == SO_RCVTIMEO || option == SO_SNDTIMEO)) { struct timeval tmo; - socklen_t len = sizeof(struct timeval); - ret = getsockopt(sock.fd, SOL_SOCKET, option, &tmo, &len); + len = sizeof(struct timeval); + ret = getsockopt(sock.fd, level, option, &tmo, &len); if (ret == 0) { rsp_send("\r\n#XSOCKETOPT: %ld\r\n", (long)tmo.tv_sec); } - } break; - - default: - ret = -ENOTSUP; - LOG_WRN("Unsupported option: %d", option); - break; + } else { + /* Default */ + ret = getsockopt(sock.fd, level, option, &value, &len); + if (ret == 0) { + rsp_send("\r\n#XSOCKETOPT: %d\r\n", value); + } } - if (ret && ret != -ENOTSUP) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); + if (ret) { + LOG_ERR("getsockopt(%d,%d) error: %d", level, option, -errno); } return ret; } -static int do_secure_socketopt_set_str(int option, const char *value) +static int at_sec_sockopt_to_sockopt(enum at_sec_sockopt at_option, int *level, int *option) { - int ret = 0; + *level = SOL_TLS; - switch (option) { - case TLS_HOSTNAME: - /** Write-only socket option to set hostname. It accepts a string containing - * the hostname (may be NULL to disable hostname verification). - */ - if (slm_util_casecmp(value, "NULL")) { - ret = setsockopt(sock.fd, SOL_TLS, option, NULL, 0); - } else { - ret = setsockopt(sock.fd, SOL_TLS, option, value, strlen(value)); - } + switch (at_option) { + case AT_TLS_HOSTNAME: + *option = TLS_HOSTNAME; break; - - default: - ret = -ENOTSUP; - LOG_WRN("Unsupported option: %d", option); + case AT_TLS_CIPHERSUITE_USED: + *option = TLS_CIPHERSUITE_USED; break; + case AT_TLS_PEER_VERIFY: + *option = TLS_PEER_VERIFY; + break; + case AT_TLS_SESSION_CACHE: + *option = TLS_SESSION_CACHE; + break; + case AT_TLS_SESSION_CACHE_PURGE: + *option = TLS_SESSION_CACHE_PURGE; + break; + case AT_TLS_DTLS_CID: + *option = TLS_DTLS_CID; + break; + case AT_TLS_DTLS_CID_STATUS: + *option = TLS_DTLS_CID_STATUS; + break; + case AT_TLS_DTLS_HANDSHAKE_TIMEO: + *option = TLS_DTLS_HANDSHAKE_TIMEO; + break; + default: + LOG_WRN("Unsupported option: %d", at_option); + return -ENOTSUP; } - if (ret && ret != -ENOTSUP) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); - } - - return ret; + return 0; } -static int do_secure_socketopt_set_int(int option, int value) +static int sec_sockopt_set(enum at_sec_sockopt at_option, void *value, socklen_t len) { - int ret = 0; + int ret, level, option; - switch (option) { - case TLS_PEER_VERIFY: - case TLS_SESSION_CACHE: - case TLS_SESSION_CACHE_PURGE: - case TLS_DTLS_HANDSHAKE_TIMEO: - case TLS_DTLS_CID: - ret = setsockopt(sock.fd, SOL_TLS, option, &value, sizeof(value)); - if (ret) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); - } - break; + ret = at_sec_sockopt_to_sockopt(at_option, &level, &option); + if (ret) { + return ret; + } - default: - ret = -ENOTSUP; - LOG_WRN("Unsupported option: %d", option); - break; + /* Options with special handling. */ + if (level == SOL_TLS && option == TLS_HOSTNAME) { + if (slm_util_casecmp(value, "NULL")) { + value = NULL; + len = 0; + } + } else if (len != sizeof(int)) { + return -EINVAL; } - if (ret && ret != -ENOTSUP) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); + ret = setsockopt(sock.fd, level, option, value, len); + if (ret) { + LOG_ERR("setsockopt(%d,%d) error: %d", level, option, -errno); } return ret; } -static int do_secure_socketopt_get(int option) + +static int sec_sockopt_get(enum at_sec_sockopt at_option) { - int ret = 0; - int value; + int ret, value, level, option; socklen_t len = sizeof(int); - switch (option) { - case TLS_CIPHERSUITE_USED: /* MFW >= 2.0.0 */ - ret = getsockopt(sock.fd, SOL_TLS, option, &value, &len); + ret = at_sec_sockopt_to_sockopt(at_option, &level, &option); + if (ret) { + return ret; + } + + /* Options with special handling. */ + if (level == SOL_TLS && option == TLS_CIPHERSUITE_USED) { + ret = getsockopt(sock.fd, level, option, &value, &len); if (ret == 0) { rsp_send("\r\n#XSSOCKETOPT: 0x%x\r\n", value); } - break; - case TLS_DTLS_CID_STATUS: - case TLS_PEER_VERIFY: - case TLS_SESSION_CACHE: - case TLS_DTLS_HANDSHAKE_TIMEO: - ret = getsockopt(sock.fd, SOL_TLS, option, &value, &len); + } else if (level == SOL_TLS && option == TLS_HOSTNAME) { + char hostname[SLM_MAX_URL] = {0}; + + len = sizeof(hostname); + ret = getsockopt(sock.fd, level, option, &hostname, &len); + if (ret == 0) { + rsp_send("\r\n#XSSOCKETOPT: %s\r\n", hostname); + } + } else { + /* Default */ + ret = getsockopt(sock.fd, level, option, &value, &len); if (ret == 0) { rsp_send("\r\n#XSSOCKETOPT: %d\r\n", value); } - break; - - default: - ret = -ENOTSUP; - LOG_WRN("Unsupported option: %d", option); - break; } - if (ret && ret != -ENOTSUP) { - LOG_ERR("setsockopt(%d) error: %d", option, -errno); + if (ret) { + LOG_ERR("getsockopt(%d,%d) error: %d", level, option, -errno); } return ret; @@ -583,7 +627,7 @@ static int do_connect(const char *url, uint16_t port) }; LOG_DBG("connect %s:%d", url, port); - ret = util_resolve_host(sock.cid, url, port, sock.family, Z_LOG_OBJECT_PTR(slm_sock), &sa); + ret = util_resolve_host(sock.cid, url, port, sock.family, &sa); if (ret) { return -EAGAIN; } @@ -676,10 +720,6 @@ static int do_send(const uint8_t *data, int datalen) uint32_t offset = 0; while (offset < datalen) { - ret = socket_poll(sockfd, POLLOUT, SOCKET_SEND_TMO_SEC); - if (ret) { - break; - } ret = send(sockfd, data + offset, datalen - offset, 0); if (ret < 0) { LOG_ERR("send() failed: %d, sent: %d", -errno, offset); @@ -716,10 +756,6 @@ static int do_send_datamode(const uint8_t *data, int datalen) uint32_t offset = 0; while (offset < datalen) { - ret = socket_poll(sockfd, POLLOUT, SOCKET_SEND_TMO_SEC); - if (ret) { - break; - } ret = send(sockfd, data + offset, datalen - offset, 0); if (ret < 0) { LOG_ERR("send() failed: %d, sent: %d", -errno, offset); @@ -745,10 +781,12 @@ static int do_recv(int timeout, int flags) return -EINVAL; } } + struct timeval tmo = {.tv_sec = timeout}; - ret = socket_poll(sockfd, POLLIN, timeout); + ret = setsockopt(sock.fd, SOL_SOCKET, SO_RCVTIMEO, &tmo, sizeof(tmo)); if (ret) { - return ret; + LOG_ERR("setsockopt(%d) error: %d", SO_RCVTIMEO, -errno); + return -errno; } ret = recv(sockfd, (void *)slm_data_buf, sizeof(slm_data_buf), flags); if (ret < 0) { @@ -782,16 +820,12 @@ static int do_sendto(const char *url, uint16_t port, const uint8_t *data, int da }; LOG_DBG("sendto %s:%d", url, port); - ret = util_resolve_host(sock.cid, url, port, sock.family, Z_LOG_OBJECT_PTR(slm_sock), &sa); + ret = util_resolve_host(sock.cid, url, port, sock.family, &sa); if (ret) { return -EAGAIN; } while (offset < datalen) { - ret = socket_poll(sock.fd, POLLOUT, SOCKET_SEND_TMO_SEC); - if (ret) { - break; - } if (sa.sa_family == AF_INET) { ret = sendto(sock.fd, data + offset, datalen - offset, 0, &sa, sizeof(struct sockaddr_in)); @@ -824,8 +858,7 @@ static int do_sendto_datamode(const uint8_t *data, int datalen) }; LOG_DBG("sendto %s:%d", udp_url, udp_port); - ret = util_resolve_host(sock.cid, udp_url, udp_port, sock.family, - Z_LOG_OBJECT_PTR(slm_sock), &sa); + ret = util_resolve_host(sock.cid, udp_url, udp_port, sock.family, &sa); if (ret) { return -EAGAIN; } @@ -833,10 +866,6 @@ static int do_sendto_datamode(const uint8_t *data, int datalen) uint32_t offset = 0; while (offset < datalen) { - ret = socket_poll(sock.fd, POLLOUT, SOCKET_SEND_TMO_SEC); - if (ret) { - break; - } if (sa.sa_family == AF_INET) { ret = sendto(sock.fd, data + offset, datalen - offset, 0, &sa, sizeof(struct sockaddr_in)); @@ -859,10 +888,12 @@ static int do_recvfrom(int timeout, int flags) int ret; struct sockaddr remote; socklen_t addrlen = sizeof(struct sockaddr); + struct timeval tmo = {.tv_sec = timeout}; - ret = socket_poll(sock.fd, POLLIN, timeout); + ret = setsockopt(sock.fd, SOL_SOCKET, SO_RCVTIMEO, &tmo, sizeof(tmo)); if (ret) { - return ret; + LOG_ERR("setsockopt(%d) error: %d", SO_RCVTIMEO, -errno); + return -errno; } ret = recvfrom( sock.fd, (void *)slm_data_buf, sizeof(slm_data_buf), flags, &remote, &addrlen); @@ -975,15 +1006,17 @@ static int socket_datamode_callback(uint8_t op, const uint8_t *data, int len, ui return ret; } -/* Handles AT#XSOCKET commands. */ -int handle_at_socket(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsocket_set, "AT#XSOCKET=", handle_at_socket); +SLM_AT_CMD_CUSTOM(xsocket_read, "AT#XSOCKET?", handle_at_socket); +static int handle_at_socket(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -993,18 +1026,17 @@ int handle_at_socket(enum at_cmd_type cmd_type) return -EINVAL; } INIT_SOCKET(sock); - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &sock.type); + err = at_params_unsigned_short_get(param_list, 2, &sock.type); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &sock.role); + err = at_params_unsigned_short_get(param_list, 3, &sock.role); if (err) { return err; } sock.family = (op == AT_SOCKET_OPEN) ? AF_INET : AF_INET6; - if (at_params_valid_count_get(&slm_at_param_list) > 4) { - err = at_params_unsigned_short_get( - &slm_at_param_list, 4, &sock.cid); + if (param_count > 4) { + err = at_params_unsigned_short_get(param_list, 4, &sock.cid); if (err) { return err; } @@ -1042,15 +1074,17 @@ int handle_at_socket(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XSOCKET commands. */ -int handle_at_secure_socket(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xssocket_set, "AT#XSSOCKET=", handle_at_secure_socket); +SLM_AT_CMD_CUSTOM(xssocket_read, "AT#XSSOCKET?", handle_at_secure_socket); +static int handle_at_secure_socket(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t param_count) { int err = -EINVAL; uint16_t op; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -1069,11 +1103,11 @@ int handle_at_secure_socket(enum at_cmd_type cmd_type) return -EINVAL; } INIT_SOCKET(sock); - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &sock.type); + err = at_params_unsigned_short_get(param_list, 2, &sock.type); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &sock.role); + err = at_params_unsigned_short_get(param_list, 3, &sock.role); if (err) { return err; } @@ -1084,21 +1118,20 @@ int handle_at_secure_socket(enum at_cmd_type cmd_type) } else { return -EINVAL; } - err = at_params_unsigned_int_get(&slm_at_param_list, 4, &sock.sec_tag); + sock.sec_tag = INVALID_SEC_TAG; + err = at_params_unsigned_int_get(param_list, 4, &sock.sec_tag); if (err) { return err; } - if (at_params_valid_count_get(&slm_at_param_list) > 5) { - err = at_params_unsigned_short_get(&slm_at_param_list, 5, - &peer_verify); + if (param_count > 5) { + err = at_params_unsigned_short_get(param_list, 5, &peer_verify); if (err) { return err; } } sock.family = (op == AT_SOCKET_OPEN) ? AF_INET : AF_INET6; - if (at_params_valid_count_get(&slm_at_param_list) > 6) { - err = at_params_unsigned_short_get( - &slm_at_param_list, 6, &sock.cid); + if (param_count > 6) { + err = at_params_unsigned_short_get(param_list, 6, &sock.cid); if (err) { return err; } @@ -1137,15 +1170,16 @@ int handle_at_secure_socket(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XSOCKETSELECT commands. */ -int handle_at_socket_select(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsocketselect, "AT#XSOCKETSELECT", handle_at_socket_select); +static int handle_at_socket_select(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t) { int err = 0; int fd; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_int_get(&slm_at_param_list, 1, &fd); + err = at_params_int_get(param_list, 1, &fd); if (err) { return err; } @@ -1181,11 +1215,11 @@ int handle_at_socket_select(enum at_cmd_type cmd_type) } return err; - } -/* Handles AT#XSOCKETOPT commands. */ -int handle_at_socketopt(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsocketopt, "AT#XSOCKETOPT", handle_at_socketopt); +static int handle_at_socketopt(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; @@ -1194,25 +1228,26 @@ int handle_at_socketopt(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &name); + err = at_params_unsigned_short_get(param_list, 2, &name); if (err) { return err; } if (op == AT_SOCKETOPT_SET) { /* some options don't require a value */ - if (at_params_valid_count_get(&slm_at_param_list) > 3) { - err = at_params_int_get(&slm_at_param_list, 3, &value); + if (param_count > 3) { + err = at_params_int_get(param_list, 3, &value); if (err) { return err; } } - err = do_socketopt_set(name, value); + + err = sockopt_set(name, value); } else if (op == AT_SOCKETOPT_GET) { - err = do_socketopt_get(name); + err = sockopt_get(name); } break; case AT_CMD_TYPE_TEST_COMMAND: @@ -1228,8 +1263,9 @@ int handle_at_socketopt(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XSSOCKETOPT commands. */ -int handle_at_secure_socketopt(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xssocketopt, "AT#XSSOCKETOPT", handle_at_secure_socketopt); +static int handle_at_secure_socketopt(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t) { int err = -EINVAL; uint16_t op; @@ -1242,11 +1278,11 @@ int handle_at_secure_socketopt(enum at_cmd_type cmd_type) LOG_ERR("Not secure socket"); return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &name); + err = at_params_unsigned_short_get(param_list, 2, &name); if (err) { return err; } @@ -1255,24 +1291,24 @@ int handle_at_secure_socketopt(enum at_cmd_type cmd_type) char value_str[SLM_MAX_URL] = {0}; int size = SLM_MAX_URL; - type = at_params_type_get(&slm_at_param_list, 3); + type = at_params_type_get(param_list, 3); if (type == AT_PARAM_TYPE_NUM_INT) { - err = at_params_int_get(&slm_at_param_list, 3, &value_int); + err = at_params_int_get(param_list, 3, &value_int); if (err) { return err; } - err = do_secure_socketopt_set_int(name, value_int); + err = sec_sockopt_set(name, &value_int, sizeof(value_int)); } else if (type == AT_PARAM_TYPE_STRING) { - err = util_string_get(&slm_at_param_list, 3, value_str, &size); + err = util_string_get(param_list, 3, value_str, &size); if (err) { return err; } - err = do_secure_socketopt_set_str(name, value_str); + err = sec_sockopt_set(name, value_str, strlen(value_str)); } else { return -EINVAL; } } else if (op == AT_SOCKETOPT_GET) { - err = do_secure_socketopt_get(name); + err = sec_sockopt_get(name); } break; case AT_CMD_TYPE_TEST_COMMAND: @@ -1288,15 +1324,16 @@ int handle_at_secure_socketopt(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XBIND commands. */ -int handle_at_bind(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xbind, "AT#XBIND", handle_at_bind); +static int handle_at_bind(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint16_t port; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &port); + err = at_params_unsigned_short_get(param_list, 1, &port); if (err < 0) { return err; } @@ -1310,8 +1347,9 @@ int handle_at_bind(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XCONNECT commands. */ -int handle_at_connect(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xconnect, "AT#XCONNECT", handle_at_connect); +static int handle_at_connect(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; char url[SLM_MAX_URL] = {0}; @@ -1325,11 +1363,11 @@ int handle_at_connect(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = util_string_get(&slm_at_param_list, 1, url, &size); + err = util_string_get(param_list, 1, url, &size); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &port); + err = at_params_unsigned_short_get(param_list, 2, &port); if (err) { return err; } @@ -1343,8 +1381,8 @@ int handle_at_connect(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XLISTEN commands. */ -int handle_at_listen(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xlisten, "AT#XLISTEN", handle_at_listen); +static int handle_at_listen(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { int err = -EINVAL; @@ -1365,8 +1403,9 @@ int handle_at_listen(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XACCEPT command. */ -int handle_at_accept(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xaccept, "AT#XACCEPT", handle_at_accept); +static int handle_at_accept(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; int timeout; @@ -1378,7 +1417,7 @@ int handle_at_accept(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_int_get(&slm_at_param_list, 1, &timeout); + err = at_params_int_get(param_list, 1, &timeout); if (err) { return err; } @@ -1401,18 +1440,29 @@ int handle_at_accept(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XSEND command. */ -int handle_at_send(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsend, "AT#XSEND", handle_at_send); +static int handle_at_send(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { + const char *at_cmd; + size_t at_cmd_len; + + if (at_params_string_ptr_get(param_list, 0, &at_cmd, &at_cmd_len)) { + return -EINVAL; + } + if (!strncasecmp(at_cmd, "AT#XSENDTO", strlen("AT#XSENDTO"))) { + return handle_at_sendto(cmd_type, param_list, param_count); + } + int err = -EINVAL; char data[SLM_MAX_PAYLOAD_SIZE + 1] = {0}; int size; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) > 1) { + if (param_count > 1) { size = sizeof(data); - err = util_string_get(&slm_at_param_list, 1, data, &size); + err = util_string_get(param_list, 1, data, &size); if (err) { return err; } @@ -1429,8 +1479,10 @@ int handle_at_send(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XRECV command. */ -int handle_at_recv(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xrecv_set, "AT#XRECV=", handle_at_recv); +SLM_AT_CMD_CUSTOM(xrecv_read, "AT#XRECV?", handle_at_recv); +static int handle_at_recv(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; int timeout; @@ -1438,12 +1490,12 @@ int handle_at_recv(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_int_get(&slm_at_param_list, 1, &timeout); + err = at_params_int_get(param_list, 1, &timeout); if (err) { return err; } - if (at_params_valid_count_get(&slm_at_param_list) > 2) { - err = at_params_int_get(&slm_at_param_list, 2, &flags); + if (param_count > 2) { + err = at_params_int_get(param_list, 2, &flags); if (err) { return err; } @@ -1458,28 +1510,30 @@ int handle_at_recv(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XSENDTO command. */ -int handle_at_sendto(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xsendto, "AT#XSENDTO", handle_at_sendto); +static int handle_at_sendto(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { + int err = -EINVAL; int size; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: size = sizeof(udp_url); - err = util_string_get(&slm_at_param_list, 1, udp_url, &size); + err = util_string_get(param_list, 1, udp_url, &size); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &udp_port); + err = at_params_unsigned_short_get(param_list, 2, &udp_port); if (err) { return err; } - if (at_params_valid_count_get(&slm_at_param_list) > 3) { + if (param_count > 3) { char data[SLM_MAX_PAYLOAD_SIZE + 1] = {0}; size = sizeof(data); - err = util_string_get(&slm_at_param_list, 3, data, &size); + err = util_string_get(param_list, 3, data, &size); if (err) { return err; } @@ -1497,8 +1551,9 @@ int handle_at_sendto(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XRECVFROM command. */ -int handle_at_recvfrom(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xrecvfrom, "AT#XRECVFROM", handle_at_recvfrom); +static int handle_at_recvfrom(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; int timeout; @@ -1506,12 +1561,12 @@ int handle_at_recvfrom(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_int_get(&slm_at_param_list, 1, &timeout); + err = at_params_int_get(param_list, 1, &timeout); if (err) { return err; } - if (at_params_valid_count_get(&slm_at_param_list) > 2) { - err = at_params_int_get(&slm_at_param_list, 2, &flags); + if (param_count > 2) { + err = at_params_int_get(param_list, 2, &flags); if (err) { return err; } @@ -1526,8 +1581,9 @@ int handle_at_recvfrom(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XGETADDRINFO command. */ -int handle_at_getaddrinfo(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xgetaddrinfo, "AT#XGETADDRINFO", handle_at_getaddrinfo); +static int handle_at_getaddrinfo(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; char hostname[NI_MAXHOST]; @@ -1539,7 +1595,7 @@ int handle_at_getaddrinfo(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = util_string_get(&slm_at_param_list, 1, host, &size); + err = util_string_get(param_list, 1, host, &size); if (err) { return err; } @@ -1584,20 +1640,20 @@ int handle_at_getaddrinfo(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XPOLL command. */ -int handle_at_poll(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xpoll, "AT#XPOLL", handle_at_poll); +static int handle_at_poll(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; int timeout, handle; - int count = at_params_valid_count_get(&slm_at_param_list); switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_int_get(&slm_at_param_list, 1, &timeout); + err = at_params_int_get(param_list, 1, &timeout); if (err) { return err; } - if (count == 2) { + if (param_count == 2) { /* poll all opened socket */ for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) { fds[i].fd = socks[i].fd; @@ -1609,8 +1665,8 @@ int handle_at_poll(enum at_cmd_type cmd_type) /* poll selected sockets */ for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) { fds[i].fd = INVALID_SOCKET; - if (count > 2 + i) { - err = at_params_int_get(&slm_at_param_list, 2 + i, &handle); + if (param_count > 2 + i) { + err = at_params_int_get(param_list, 2 + i, &handle); if (err) { return err; } diff --git a/applications/serial_lte_modem/src/slm_at_tcp_proxy.c b/applications/serial_lte_modem/src/slm_at_tcp_proxy.c index 491fe1a7af2..f9075ba3df8 100644 --- a/applications/serial_lte_modem/src/slm_at_tcp_proxy.c +++ b/applications/serial_lte_modem/src/slm_at_tcp_proxy.c @@ -8,19 +8,19 @@ #include #include #include +#include #include "slm_util.h" -#include "slm_native_tls.h" #include "slm_at_host.h" #include "slm_at_tcp_proxy.h" +#if defined(CONFIG_SLM_NATIVE_TLS) +#include "slm_native_tls.h" +#endif LOG_MODULE_REGISTER(slm_tcp, CONFIG_SLM_LOG_LEVEL); #define THREAD_STACK_SIZE KB(4) #define THREAD_PRIORITY K_LOWEST_APPLICATION_THREAD_PRIO -/* Some features need future modem firmware support */ -#define SLM_TCP_PROXY_FUTURE_FEATURE 0 - /**@brief Proxy operations. */ enum slm_tcp_proxy_operation { SERVER_STOP, @@ -60,32 +60,11 @@ static int do_tcp_server_start(uint16_t port) int ret; int reuseaddr = 1; -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - ret = slm_tls_loadcrdl(proxy.sec_tag); - if (ret < 0) { - LOG_ERR("Fail to load credential: %d", ret); - return -EAGAIN; - } - } -#else -#if !SLM_TCP_PROXY_FUTURE_FEATURE -/* TLS server not officially supported by modem yet */ - if (proxy.sec_tag != INVALID_SEC_TAG) { - LOG_ERR("Not supported"); - return -ENOTSUP; - } -#endif -#endif /* Open socket */ if (proxy.sec_tag == INVALID_SEC_TAG) { ret = socket(proxy.family, SOCK_STREAM, IPPROTO_TCP); } else { -#if defined(CONFIG_SLM_NATIVE_TLS) - ret = socket(proxy.family, SOCK_STREAM | SOCK_NATIVE_TLS, IPPROTO_TLS_1_2); -#else ret = socket(proxy.family, SOCK_STREAM, IPPROTO_TLS_1_2); -#endif } if (ret < 0) { LOG_ERR("socket() failed: %d", -errno); @@ -94,36 +73,35 @@ static int do_tcp_server_start(uint16_t port) } proxy.sock = ret; - /* Config socket options */ if (proxy.sec_tag != INVALID_SEC_TAG) { - sec_tag_t sec_tag_list[1] = { proxy.sec_tag }; - - ret = setsockopt(proxy.sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, - sizeof(sec_tag_t)); - if (ret) { - LOG_ERR("setsockopt(TLS_SEC_TAG_LIST) error: %d", -errno); - ret = -errno; - goto exit_svr; +#ifndef CONFIG_SLM_NATIVE_TLS + LOG_ERR("Not supported"); + return -ENOTSUP; +#else + ret = slm_native_tls_load_credentials(proxy.sec_tag); + if (ret < 0) { + LOG_ERR("Failed to load sec tag: %d (%d)", proxy.sec_tag, ret); + return ret; } -#if SLM_TCP_PROXY_FUTURE_FEATURE -/* TLS server not officially supported by modem yet */ - int tls_role = TLS_DTLS_ROLE_SERVER; - int peer_verify = TLS_PEER_VERIFY_NONE; + int tls_native = 1; - ret = setsockopt(proxy.sock, SOL_TLS, TLS_DTLS_ROLE, &tls_role, sizeof(int)); + /* Must be the first socket option to set. */ + ret = setsockopt(proxy.sock, SOL_TLS, TLS_NATIVE, &tls_native, + sizeof(tls_native)); if (ret) { - LOG_ERR("setsockopt(TLS_DTLS_ROLE) error: %d", -errno); - ret = -errno; + ret = errno; goto exit_svr; } - ret = setsockopt(proxy.sock, SOL_TLS, TLS_PEER_VERIFY, &peer_verify, - sizeof(peer_verify)); +#endif + sec_tag_t sec_tag_list[1] = { proxy.sec_tag }; + + ret = setsockopt(proxy.sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, + sizeof(sec_tag_t)); if (ret) { - LOG_ERR("setsockopt(TLS_PEER_VERIFY) error: %d", errno); + LOG_ERR("setsockopt(TLS_SEC_TAG_LIST) error: %d", -errno); ret = -errno; goto exit_svr; } -#endif } ret = setsockopt(proxy.sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)); @@ -201,12 +179,6 @@ static int do_tcp_server_start(uint16_t port) return 0; exit_svr: -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(proxy.sec_tag); - proxy.sec_tag = INVALID_SEC_TAG; - } -#endif if (proxy.sock != INVALID_SOCKET) { close(proxy.sock); proxy.sock = INVALID_SOCKET; @@ -223,12 +195,6 @@ static int do_tcp_server_stop(void) if (proxy.sock == INVALID_SOCKET) { return 0; } -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(proxy.sec_tag); - proxy.sec_tag = INVALID_SEC_TAG; - } -#endif server_stop_pending = true; if (proxy.sock_peer != INVALID_SOCKET) { (void)close(proxy.sock_peer); @@ -259,11 +225,7 @@ static int do_tcp_client_connect(const char *url, uint16_t port) if (proxy.sec_tag == INVALID_SEC_TAG) { ret = socket(proxy.family, SOCK_STREAM, IPPROTO_TCP); } else { -#if defined(CONFIG_SLM_NATIVE_TLS) - ret = socket(proxy.family, SOCK_STREAM | SOCK_NATIVE_TLS, IPPROTO_TLS_1_2); -#else ret = socket(proxy.family, SOCK_STREAM, IPPROTO_TLS_1_2); -#endif } if (ret < 0) { LOG_ERR("socket() failed: %d", -errno); @@ -272,14 +234,23 @@ static int do_tcp_client_connect(const char *url, uint16_t port) proxy.sock = ret; if (proxy.sec_tag != INVALID_SEC_TAG) { - sec_tag_t sec_tag_list[1] = { proxy.sec_tag }; #if defined(CONFIG_SLM_NATIVE_TLS) - ret = slm_tls_loadcrdl(proxy.sec_tag); + ret = slm_native_tls_load_credentials(proxy.sec_tag); if (ret < 0) { - LOG_ERR("Fail to load credential: %d", ret); + LOG_ERR("Failed to load sec tag: %d (%d)", proxy.sec_tag, ret); + goto exit_cli; + } + int tls_native = 1; + + /* Must be the first socket option to set. */ + ret = setsockopt(proxy.sock, SOL_TLS, TLS_NATIVE, &tls_native, sizeof(tls_native)); + if (ret) { + ret = errno; goto exit_cli; } #endif + sec_tag_t sec_tag_list[1] = { proxy.sec_tag }; + ret = setsockopt(proxy.sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, sizeof(sec_tag_t)); if (ret) { @@ -307,7 +278,7 @@ static int do_tcp_client_connect(const char *url, uint16_t port) } /* Connect to remote host */ - ret = util_resolve_host(0, url, port, proxy.family, Z_LOG_OBJECT_PTR(slm_tcp), &sa); + ret = util_resolve_host(0, url, port, proxy.family, &sa); if (ret) { goto exit_cli; } @@ -333,12 +304,6 @@ static int do_tcp_client_connect(const char *url, uint16_t port) return 0; exit_cli: -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(proxy.sec_tag); - proxy.sec_tag = INVALID_SEC_TAG; - } -#endif close(proxy.sock); proxy.sock = INVALID_SOCKET; rsp_send("\r\n#XTCPCLI: %d,\"not connected\"\r\n", ret); @@ -353,12 +318,6 @@ static int do_tcp_client_disconnect(void) if (proxy.sock == INVALID_SOCKET) { return 0; } -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(proxy.sec_tag); - proxy.sec_tag = INVALID_SEC_TAG; - } -#endif ret = close(proxy.sock); if (ret < 0) { LOG_WRN("close() failed: %d", -errno); @@ -557,8 +516,8 @@ static void tcpsvr_thread_func(void *p1, void *p2, void *p3) /* Process POLLIN first to get the data, even if there are errors. */ if ((fds[1].revents & POLLIN) == POLLIN) { ret = recv(fds[1].fd, (void *)slm_data_buf, - sizeof(slm_data_buf), 0); - if (ret < 0) { + sizeof(slm_data_buf), MSG_DONTWAIT); + if (ret < 0 && errno != EAGAIN) { LOG_ERR("recv() error: %d", -errno); tcpsvr_terminate_connection(-errno); fds[1].fd = INVALID_SOCKET; @@ -591,12 +550,6 @@ static void tcpsvr_thread_func(void *p1, void *p2, void *p3) } } -#if defined(CONFIG_SLM_NATIVE_TLS) - if (proxy.sec_tag != INVALID_SEC_TAG) { - (void)slm_tls_unloadcrdl(proxy.sec_tag); - proxy.sec_tag = INVALID_SEC_TAG; - } -#endif tcpsvr_terminate_connection(ret); if (proxy.sock != INVALID_SOCKET) { (void)close(proxy.sock); @@ -650,8 +603,8 @@ static void tcpcli_thread_func(void *p1, void *p2, void *p3) if ((fds.revents & POLLIN) != POLLIN) { continue; } - ret = recv(fds.fd, (void *)slm_data_buf, sizeof(slm_data_buf), 0); - if (ret < 0) { + ret = recv(fds.fd, (void *)slm_data_buf, sizeof(slm_data_buf), MSG_DONTWAIT); + if (ret < 0 && errno != EAGAIN) { LOG_WRN("recv() error: %d", -errno); continue; } @@ -678,17 +631,17 @@ static void tcpcli_thread_func(void *p1, void *p2, void *p3) LOG_INF("TCP client thread terminated"); } -/* Handles AT#XTCPSVR commands. */ -int handle_at_tcp_server(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtcpsvr, "AT#XTCPSVR", handle_at_tcp_server); +static int handle_at_tcp_server(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; uint16_t port; - int param_count = at_params_valid_count_get(&slm_at_param_list); switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -697,13 +650,13 @@ int handle_at_tcp_server(enum at_cmd_type cmd_type) LOG_ERR("Server is running."); return -EINVAL; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &port); + err = at_params_unsigned_short_get(param_list, 2, &port); if (err) { return err; } proxy.sec_tag = INVALID_SEC_TAG; if (param_count > 3) { - err = at_params_int_get(&slm_at_param_list, 3, &proxy.sec_tag); + err = at_params_int_get(param_list, 3, &proxy.sec_tag); if (err) { return err; } @@ -733,16 +686,16 @@ int handle_at_tcp_server(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTCPCLI commands. */ -int handle_at_tcp_client(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtcpcli, "AT#XTCPCLI", handle_at_tcp_client); +static int handle_at_tcp_client(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; - int param_count = at_params_valid_count_get(&slm_at_param_list); switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -755,22 +708,22 @@ int handle_at_tcp_client(enum at_cmd_type cmd_type) LOG_ERR("Client is connected."); return -EINVAL; } - err = util_string_get(&slm_at_param_list, 2, url, &size); + err = util_string_get(param_list, 2, url, &size); if (err) { return err; } - if (at_params_unsigned_short_get(&slm_at_param_list, 3, &port)) { + if (at_params_unsigned_short_get(param_list, 3, &port)) { return -EINVAL; } proxy.sec_tag = INVALID_SEC_TAG; if (param_count > 4) { - if (at_params_int_get(&slm_at_param_list, 4, &proxy.sec_tag)) { + if (at_params_int_get(param_list, 4, &proxy.sec_tag)) { return -EINVAL; } } proxy.peer_verify = TLS_PEER_VERIFY_REQUIRED; if (param_count > 5) { - if (at_params_int_get(&slm_at_param_list, 5, &proxy.peer_verify) || + if (at_params_int_get(param_list, 5, &proxy.peer_verify) || (proxy.peer_verify != TLS_PEER_VERIFY_NONE && proxy.peer_verify != TLS_PEER_VERIFY_OPTIONAL && proxy.peer_verify != TLS_PEER_VERIFY_REQUIRED)) { @@ -781,8 +734,7 @@ int handle_at_tcp_client(enum at_cmd_type cmd_type) if (param_count > 6) { uint16_t hostname_verify; - if (at_params_unsigned_short_get(&slm_at_param_list, 6, - &hostname_verify) || + if (at_params_unsigned_short_get(param_list, 6, &hostname_verify) || (hostname_verify != 0 && hostname_verify != 1)) { return -EINVAL; } @@ -814,8 +766,9 @@ int handle_at_tcp_client(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTCPSEND command. */ -int handle_at_tcp_send(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtcpsend, "AT#XTCPSEND", handle_at_tcp_send); +static int handle_at_tcp_send(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; char data[SLM_MAX_PAYLOAD_SIZE + 1] = {0}; @@ -823,9 +776,9 @@ int handle_at_tcp_send(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) > 1) { + if (at_params_valid_count_get(param_list) > 1) { size = sizeof(data); - err = util_string_get(&slm_at_param_list, 1, data, &size); + err = util_string_get(param_list, 1, data, &size); if (err) { return err; } @@ -842,8 +795,9 @@ int handle_at_tcp_send(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTCPHANGUP commands. */ -int handle_at_tcp_hangup(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtcphangup, "AT#XTCPHANGUP", handle_at_tcp_hangup); +static int handle_at_tcp_hangup(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; int handle; @@ -853,7 +807,7 @@ int handle_at_tcp_hangup(enum at_cmd_type cmd_type) if (proxy.role != TCP_ROLE_SERVER || proxy.sock_peer == INVALID_SOCKET) { return -EINVAL; } - err = at_params_int_get(&slm_at_param_list, 1, &handle); + err = at_params_int_get(param_list, 1, &handle); if (err) { return err; } diff --git a/applications/serial_lte_modem/src/slm_at_udp_proxy.c b/applications/serial_lte_modem/src/slm_at_udp_proxy.c index e7a839a5159..51d2af7c949 100644 --- a/applications/serial_lte_modem/src/slm_at_udp_proxy.c +++ b/applications/serial_lte_modem/src/slm_at_udp_proxy.c @@ -228,7 +228,7 @@ static int do_udp_client_connect(const char *url, uint16_t port) } /* Connect to remote host */ - ret = util_resolve_host(0, url, port, proxy.family, Z_LOG_OBJECT_PTR(slm_udp), &sa); + ret = util_resolve_host(0, url, port, proxy.family, &sa); if (ret) { goto cli_exit; } @@ -504,8 +504,9 @@ static bool socket_is_in_use(void) return true; } -/* Handles AT#XUDPSVR commands. */ -int handle_at_udp_server(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xudpsvr, "AT#XUDPSVR", handle_at_udp_server); +static int handle_at_udp_server(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint16_t op; @@ -513,7 +514,7 @@ int handle_at_udp_server(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -521,7 +522,7 @@ int handle_at_udp_server(enum at_cmd_type cmd_type) if (socket_is_in_use()) { return -EINVAL; } - err = at_params_unsigned_short_get(&slm_at_param_list, 2, &port); + err = at_params_unsigned_short_get(param_list, 2, &port); if (err) { return err; } @@ -549,15 +550,16 @@ int handle_at_udp_server(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XUDPCLI commands. */ -int handle_at_udp_client(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xudpcli, "AT#XUDPCLI", handle_at_udp_client); +static int handle_at_udp_client(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t op; switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &op); + err = at_params_unsigned_short_get(param_list, 1, &op); if (err) { return err; } @@ -569,26 +571,25 @@ int handle_at_udp_client(enum at_cmd_type cmd_type) if (socket_is_in_use()) { return -EINVAL; } - err = util_string_get(&slm_at_param_list, 2, url, &size); + err = util_string_get(param_list, 2, url, &size); if (err) { return err; } - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &port); + err = at_params_unsigned_short_get(param_list, 3, &port); if (err) { return err; } proxy.sec_tag = INVALID_SEC_TAG; - const uint32_t param_count = at_params_valid_count_get(&slm_at_param_list); if (param_count > 4) { - if (at_params_int_get(&slm_at_param_list, 4, &proxy.sec_tag) + if (at_params_int_get(param_list, 4, &proxy.sec_tag) || proxy.sec_tag == INVALID_SEC_TAG || proxy.sec_tag < 0) { return -EINVAL; } } proxy.dtls_cid = INVALID_DTLS_CID; if (param_count > 5) { - if (at_params_int_get(&slm_at_param_list, 5, &proxy.dtls_cid) + if (at_params_int_get(param_list, 5, &proxy.dtls_cid) || !(proxy.dtls_cid == TLS_DTLS_CID_DISABLED || proxy.dtls_cid == TLS_DTLS_CID_SUPPORTED || proxy.dtls_cid == TLS_DTLS_CID_ENABLED)) { @@ -597,7 +598,7 @@ int handle_at_udp_client(enum at_cmd_type cmd_type) } proxy.peer_verify = TLS_PEER_VERIFY_REQUIRED; if (param_count > 6) { - if (at_params_int_get(&slm_at_param_list, 6, &proxy.peer_verify) || + if (at_params_int_get(param_list, 6, &proxy.peer_verify) || (proxy.peer_verify != TLS_PEER_VERIFY_NONE && proxy.peer_verify != TLS_PEER_VERIFY_OPTIONAL && proxy.peer_verify != TLS_PEER_VERIFY_REQUIRED)) { @@ -608,8 +609,7 @@ int handle_at_udp_client(enum at_cmd_type cmd_type) if (param_count > 7) { uint16_t hostname_verify; - if (at_params_unsigned_short_get(&slm_at_param_list, 7, - &hostname_verify) || + if (at_params_unsigned_short_get(param_list, 7, &hostname_verify) || (hostname_verify != 0 && hostname_verify != 1)) { return -EINVAL; } @@ -640,8 +640,9 @@ int handle_at_udp_client(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XUDPSEND command. */ -int handle_at_udp_send(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xudpsend, "AT#XUDPSEND", handle_at_udp_send); +static int handle_at_udp_send(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; char data[SLM_MAX_PAYLOAD_SIZE + 1] = {0}; @@ -653,9 +654,9 @@ int handle_at_udp_send(enum at_cmd_type cmd_type) LOG_ERR("Not connected yet"); return -ENOTCONN; } - if (at_params_valid_count_get(&slm_at_param_list) > 1) { + if (param_count > 1) { size = sizeof(data); - err = util_string_get(&slm_at_param_list, 1, data, &size); + err = util_string_get(param_list, 1, data, &size); if (err) { return err; } diff --git a/applications/serial_lte_modem/src/slm_cmux.c b/applications/serial_lte_modem/src/slm_cmux.c new file mode 100644 index 00000000000..3136e6954df --- /dev/null +++ b/applications/serial_lte_modem/src/slm_cmux.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include "slm_cmux.h" +#include "slm_at_host.h" +#if defined(CONFIG_SLM_PPP) +#include "slm_ppp.h" +#endif +#include +#include +#include +#include +#include + +/* This makes use of part of the Zephyr modem subsystem which has a CMUX module. */ +LOG_MODULE_REGISTER(slm_cmux, CONFIG_SLM_LOG_LEVEL); + +#define CHANNEL_COUNT (1 + IS_ENABLED(CONFIG_SLM_PPP)) + +#define RECV_BUF_LEN SLM_AT_MAX_CMD_LEN +/* The CMUX module reserves some spare buffer bytes. To achieve a maximum + * response length of SLM_AT_MAX_RSP_LEN (comprising the "OK" or "ERROR" + * that is sent separately), the transmit buffer must be made a bit bigger. + * 49 extra bytes was manually found to allow SLM_AT_MAX_RSP_LEN long responses. + */ +#define TRANSMIT_BUF_LEN (49 + SLM_AT_MAX_RSP_LEN) + +static struct { + /* UART backend */ + struct modem_pipe *uart_pipe; + struct modem_backend_uart uart_backend; + uint8_t uart_backend_receive_buf[RECV_BUF_LEN]; + uint8_t uart_backend_transmit_buf[TRANSMIT_BUF_LEN]; + + /* CMUX */ + struct modem_cmux instance; + uint8_t cmux_receive_buf[RECV_BUF_LEN]; + uint8_t cmux_transmit_buf[TRANSMIT_BUF_LEN]; + + /* CMUX channels (Data Link Connection Identifier); index = address - 1 */ + struct cmux_dlci { + struct modem_cmux_dlci instance; + struct modem_pipe *pipe; + uint8_t address; + uint8_t receive_buf[RECV_BUF_LEN]; + } dlcis[CHANNEL_COUNT]; + /* Index of the DLCI used for AT communication; defaults to 0. */ + unsigned int at_channel; +} cmux; + +static void dlci_pipe_event_handler(struct modem_pipe *pipe, + enum modem_pipe_event event, void *user_data) +{ + const struct cmux_dlci *const dlci = user_data; + + switch (event) { + case MODEM_PIPE_EVENT_OPENED: + case MODEM_PIPE_EVENT_CLOSED: + /* The PPP DLCI events are received here only when PPP isn't started. */ + LOG_INF("DLCI %u %s.", dlci->address, + (event == MODEM_PIPE_EVENT_OPENED) ? "opened" : "closed"); + break; + case MODEM_PIPE_EVENT_RECEIVE_READY: + static uint8_t recv_buf[RECV_BUF_LEN]; + const int recv_len = modem_pipe_receive(pipe, recv_buf, sizeof(recv_buf)); + + if (recv_len > 0) { + if (ARRAY_INDEX(cmux.dlcis, dlci) == cmux.at_channel) { + slm_at_receive(recv_buf, recv_len); + } else { + LOG_WRN("Discarding %u byte%s received on non-AT DLCI %u.", + recv_len, (recv_len > 1) ? "s" : "", dlci->address); + } + } else { + LOG_ERR("Failed to receive data on DLCI %u. (%d)", + dlci->address, recv_len); + } + break; + case MODEM_PIPE_EVENT_TRANSMIT_IDLE: + break; + } +} + +static void cmux_event_handler(struct modem_cmux *, enum modem_cmux_event event, void *) +{ + if (event == MODEM_CMUX_EVENT_CONNECTED || event == MODEM_CMUX_EVENT_DISCONNECTED) { + LOG_INF("CMUX %sconnected.", (event == MODEM_CMUX_EVENT_CONNECTED) ? "" : "dis"); + } +} + +static void init_dlci(size_t dlci_idx, uint16_t recv_buf_size, + uint8_t recv_buf[static recv_buf_size]) +{ + assert(ARRAY_SIZE(cmux.dlcis) > dlci_idx); + + struct cmux_dlci *const dlci = &cmux.dlcis[dlci_idx]; + const struct modem_cmux_dlci_config dlci_config = { + .dlci_address = dlci_idx + 1, + .receive_buf = recv_buf, + .receive_buf_size = recv_buf_size + }; + + dlci->pipe = modem_cmux_dlci_init(&cmux.instance, &dlci->instance, &dlci_config); + dlci->address = dlci_config.dlci_address; + + modem_pipe_attach(dlci->pipe, dlci_pipe_event_handler, dlci); +} + +static int cmux_write_at_channel(const uint8_t *data, size_t len) +{ + int ret = modem_pipe_transmit(cmux.dlcis[cmux.at_channel].pipe, data, len); + + if (ret != len) { + const int sent_len = MAX(0, ret); + + if (ret >= 0) { + ret = 1; + } + LOG_ERR("Sent %u out of %u AT data bytes. (%d)", sent_len, len, ret); + return ret; + } + return 0; +} + +static void close_pipe(struct modem_pipe **pipe) +{ + if (*pipe) { + modem_pipe_close_async(*pipe); + modem_pipe_release(*pipe); + *pipe = NULL; + } +} + +static int cmux_stop(void) +{ + if (cmux.uart_pipe && cmux.uart_pipe->state == MODEM_PIPE_STATE_OPEN) { + /* CMUX is running. Just close the UART pipe to pause and be able to resume. + * This allows AT data to be cached by the CMUX module while the UART is off. + */ + modem_pipe_close_async(cmux.uart_pipe); + return 0; + } + + modem_cmux_release(&cmux.instance); + + close_pipe(&cmux.uart_pipe); + + for (size_t i = 0; i != ARRAY_SIZE(cmux.dlcis); ++i) { + close_pipe(&cmux.dlcis[i].pipe); + } + + return 0; +} + +static bool cmux_is_started(void) +{ + return (cmux.uart_pipe != NULL); +} + +void slm_cmux_init(void) +{ + const struct modem_cmux_config cmux_config = { + .callback = cmux_event_handler, + .receive_buf = cmux.cmux_receive_buf, + .receive_buf_size = sizeof(cmux.cmux_receive_buf), + .transmit_buf = cmux.cmux_transmit_buf, + .transmit_buf_size = sizeof(cmux.cmux_transmit_buf), + }; + + modem_cmux_init(&cmux.instance, &cmux_config); + + for (size_t i = 0; i != ARRAY_SIZE(cmux.dlcis); ++i) { + init_dlci(i, sizeof(cmux.dlcis[i].receive_buf), cmux.dlcis[i].receive_buf); + } +} + +#if defined(CONFIG_SLM_PPP) + +static struct cmux_dlci *cmux_ppp_dlci(void) +{ + BUILD_ASSERT(ARRAY_SIZE(cmux.dlcis) == 2); + /* The DLCI that is not the AT channel's is PPP's. */ + return &cmux.dlcis[!cmux.at_channel]; +} + +struct modem_pipe *slm_cmux_reserve_ppp_channel(void) +{ + /* Return the PPP channel's pipe. PPP will attach to it, after which + * this pipe's events and data will not be received here anymore + * until the pipe is released (below) and we attach back to it. + */ + return cmux_ppp_dlci()->pipe; +} + +void slm_cmux_release_ppp_channel(void) +{ + struct cmux_dlci *ppp_dlci = cmux_ppp_dlci(); + +#if CONFIG_SLM_CMUX_AUTOMATIC_FALLBACK_ON_PPP_STOPPAGE + cmux.at_channel = 0; +#endif + + modem_pipe_attach(ppp_dlci->pipe, dlci_pipe_event_handler, ppp_dlci); +} + +#endif /* CONFIG_SLM_PPP */ + +static int cmux_start(void) +{ + int ret; + + if (cmux_is_started()) { + ret = modem_pipe_open(cmux.uart_pipe); + if (!ret) { + LOG_INF("CMUX resumed."); + } + return ret; + } + + { + const struct modem_backend_uart_config uart_backend_config = { + .uart = DEVICE_DT_GET(DT_CHOSEN(ncs_slm_uart)), + .receive_buf = cmux.uart_backend_receive_buf, + .receive_buf_size = sizeof(cmux.uart_backend_receive_buf), + .transmit_buf = cmux.uart_backend_transmit_buf, + .transmit_buf_size = sizeof(cmux.uart_backend_transmit_buf), + }; + + cmux.uart_pipe = modem_backend_uart_init(&cmux.uart_backend, &uart_backend_config); + if (!cmux.uart_pipe) { + return -ENODEV; + } + } + + ret = modem_cmux_attach(&cmux.instance, cmux.uart_pipe); + if (ret) { + return ret; + } + + ret = modem_pipe_open(cmux.uart_pipe); + return ret; +} + +static void cmux_starter(struct k_work *) +{ + const int ret = slm_at_set_backend((struct slm_at_backend) { + .start = cmux_start, + .send = cmux_write_at_channel, + .stop = cmux_stop + }); + + if (ret) { + LOG_ERR("Failed to start CMUX. (%d)", ret); + } else { + LOG_INF("CMUX started."); + } +} + +SLM_AT_CMD_CUSTOM(xcmux, "AT#XCMUX", handle_at_cmux); +static int handle_at_cmux(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) +{ + static struct k_work_delayable cmux_start_work; + unsigned int at_dlci; + int ret; + + if (cmd_type == AT_CMD_TYPE_READ_COMMAND) { + rsp_send("\r\n#XCMUX: %u,%u\r\n", cmux.at_channel + 1, CHANNEL_COUNT); + return 0; + } + if (cmd_type != AT_CMD_TYPE_SET_COMMAND || param_count > 2) { + return -EINVAL; + } + + if (param_count == 1 && cmux_is_started()) { + return -EALREADY; + } + + if (param_count == 2) { + ret = at_params_unsigned_int_get(param_list, 1, &at_dlci); + if (ret || at_dlci < 1 || at_dlci > ARRAY_SIZE(cmux.dlcis)) { + return -EINVAL; + } + const unsigned int at_channel = at_dlci - 1; + +#if defined(CONFIG_SLM_PPP) + if (slm_ppp_is_running() && at_channel != cmux.at_channel) { + /* The AT channel cannot be changed when PPP is running. */ + return -ENOTSUP; + } +#endif + if (cmux_is_started()) { + /* Just update the AT channel, first answering "OK" on the current DLCI. */ + rsp_send_ok(); + cmux.at_channel = at_channel; + return -SILENT_AT_COMMAND_RET; + } + cmux.at_channel = at_channel; + } + + k_work_init_delayable(&cmux_start_work, cmux_starter); + ret = k_work_schedule(&cmux_start_work, SLM_UART_RESPONSE_DELAY); + if (ret == 1) { + ret = 0; + } else if (ret == 0) { + ret = -EAGAIN; + } + return ret; +} diff --git a/applications/serial_lte_modem/src/slm_cmux.h b/applications/serial_lte_modem/src/slm_cmux.h new file mode 100644 index 00000000000..d8223b9488c --- /dev/null +++ b/applications/serial_lte_modem/src/slm_cmux.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#ifndef SLM_CMUX_ +#define SLM_CMUX_ + +#include + +void slm_cmux_init(void); + +#if defined(CONFIG_SLM_PPP) +struct modem_pipe; +struct modem_pipe *slm_cmux_reserve_ppp_channel(void); + +void slm_cmux_release_ppp_channel(void); +#endif /* CONFIG_SLM_PPP */ + +#endif diff --git a/applications/serial_lte_modem/src/slm_defines.h b/applications/serial_lte_modem/src/slm_defines.h index 52468715364..8c28fa3efe3 100644 --- a/applications/serial_lte_modem/src/slm_defines.h +++ b/applications/serial_lte_modem/src/slm_defines.h @@ -15,7 +15,10 @@ #define INVALID_ROLE -1 #define INVALID_DTLS_CID -1 -#define UNKNOWN_AT_COMMAND_RET __ELASTERROR +enum { + /* The command ran successfully and doesn't want the automatic response to be sent. */ + SILENT_AT_COMMAND_RET = __ELASTERROR, +}; /** The maximum allowed length of an AT command/response passed through the SLM */ #define SLM_AT_MAX_CMD_LEN 4096 @@ -33,4 +36,7 @@ #define SLM_NRF52_BLK_SIZE 4096 /** nRF52 flash block size for write operation */ #define SLM_NRF52_BLK_TIME 2000 /** nRF52 flash block write time in millisecond (1.x second) */ +#define POWER_PIN_IS_ENABLED (CONFIG_SLM_POWER_PIN != -1) +#define INDICATE_PIN_IS_ENABLED (CONFIG_SLM_INDICATE_PIN != -1) + #endif diff --git a/applications/serial_lte_modem/src/slm_native_tls.c b/applications/serial_lte_modem/src/slm_native_tls.c deleted file mode 100644 index 1307b2a0499..00000000000 --- a/applications/serial_lte_modem/src/slm_native_tls.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include "slm_native_tls.h" - -LOG_MODULE_REGISTER(slm_tls, CONFIG_SLM_LOG_LEVEL); - -/* max buffer length to load credential */ -#define MAX_CRDL_LEN 4096 - -/* pointer to credential buffer */ -static uint8_t *crdl; - -/** - * @brief Map SLM security tag to nRF security tag - */ -nrf_sec_tag_t slm_tls_map_sectag(sec_tag_t sec_tag, uint16_t type) -{ - if (sec_tag > MAX_SLM_SEC_TAG || sec_tag < MIN_SLM_SEC_TAG) { - LOG_ERR("Invalid security tag."); - return -EINVAL; - } - - return sec_tag*10 + type; -} - -/** - * @brief Load TLS credentials - */ -int slm_tls_loadcrdl(sec_tag_t sec_tag) -{ - int ret, len = MAX_CRDL_LEN, offset = 0; - bool loaded = false; - - if (sec_tag > MAX_SLM_SEC_TAG || sec_tag < MIN_SLM_SEC_TAG) { - LOG_ERR("Invalid security tag."); - return -EINVAL; - } - - crdl = k_malloc(MAX_CRDL_LEN); - if (crdl == NULL) { - LOG_ERR("Fail to allocate memory"); - return -ENOMEM; - } - memset(crdl, 0, MAX_CRDL_LEN); - - /* Load CA certificate */ - ret = modem_key_mgmt_read(slm_tls_map_sectag(sec_tag, 0), - 0, crdl + offset, &len); - if (ret == 0) { - LOG_DBG("Load CA cert %d: Len: %d", - slm_tls_map_sectag(sec_tag, 0), len); - len++; - ret = tls_credential_add(sec_tag, TLS_CREDENTIAL_CA_CERTIFICATE, - crdl + offset, len); - if (ret != 0) { - LOG_ERR("Failed to register CA certificate: %d", ret); - goto exit; - } - offset += len; - len = MAX_CRDL_LEN - offset; - loaded = true; - } else { - LOG_DBG("Empty CA cert at %d:", slm_tls_map_sectag(sec_tag, 0)); - } - - /* Load server/client certificate */ - ret = modem_key_mgmt_read(slm_tls_map_sectag(sec_tag, 1), 0, - crdl + offset, &len); - if (ret == 0) { - LOG_DBG("Load cert %d. Len: %d", - slm_tls_map_sectag(sec_tag, 1), len); - len++; - ret = tls_credential_add(sec_tag, - TLS_CREDENTIAL_SERVER_CERTIFICATE, - crdl + offset, len); - if (ret < 0) { - LOG_ERR("Failed to register public cert: %d", ret); - goto exit; - } - offset += len; - len = MAX_CRDL_LEN - offset; - loaded = true; - } else { - LOG_DBG("Empty cert at %d:", slm_tls_map_sectag(sec_tag, 1)); - } - - /* Load private key */ - ret = modem_key_mgmt_read(slm_tls_map_sectag(sec_tag, 2), 0, - crdl + offset, &len); - if (ret == 0) { - LOG_DBG("Load private key %d. Len: %d", - slm_tls_map_sectag(sec_tag, 2), len); - len++; - ret = tls_credential_add(sec_tag, TLS_CREDENTIAL_PRIVATE_KEY, - crdl + offset, len); - if (ret < 0) { - LOG_ERR("Failed to register private key: %d", ret); - goto exit; - } - loaded = true; - } else { - LOG_DBG("Empty private key at %d:", - slm_tls_map_sectag(sec_tag, 2)); - } - - if (loaded) { - /* Load credential successfully */ - return 0; - } - LOG_ERR("No credential for sec_tag:%d", sec_tag); - ret = -EINVAL; - -exit: - k_free(crdl); - crdl = NULL; - - return ret; -} - -/** - * @brief Unload TLS credentials - */ -int slm_tls_unloadcrdl(sec_tag_t sec_tag) -{ - if (sec_tag > MAX_SLM_SEC_TAG || sec_tag < MIN_SLM_SEC_TAG) { - LOG_ERR("Invalid security tag."); - return -EINVAL; - } - tls_credential_delete(sec_tag, TLS_CREDENTIAL_CA_CERTIFICATE); - tls_credential_delete(sec_tag, TLS_CREDENTIAL_SERVER_CERTIFICATE); - tls_credential_delete(sec_tag, TLS_CREDENTIAL_PRIVATE_KEY); - - k_free(crdl); - crdl = NULL; - - return 0; -} diff --git a/applications/serial_lte_modem/src/slm_native_tls.h b/applications/serial_lte_modem/src/slm_native_tls.h deleted file mode 100644 index fb117bcdf5e..00000000000 --- a/applications/serial_lte_modem/src/slm_native_tls.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef SLM_NATIVE_TLS_ -#define SLM_NATIVE_TLS_ - -/**@file slm_native_tls.h - * - * @brief Utility functions for serial LTE modem native TLS socket - * @{ - */ - -#include -#include -#include -#include "slm_trap_macros.h" - -#define MAX_SLM_SEC_TAG (INT_MAX/10) -#define MIN_SLM_SEC_TAG 0 - -/** - * @brief Map SLM security tag to nRF security tag - * When SLM native TLS is enabled, the credentials are mapped to - * continuous security tags in modem and stored as Root CA certificate - * so that the credentials can be read from modem. - * - * The available sec_tag in modem (0 – 2147483647) are divided by 10 - * to store mapped credentials: - * Root CA certificate (ASCII text) at sec_tag*10 + 0 - * Client/Server certificate (ASCII text) at sec_tag*10 + 1 - * Client/Server private key (ASCII text) at sec_tag*10 + 2 - * Pre-shared Key (PSK) at sec_tag*10 + 3 - * PSK identity (ASCII text) at sec_tag*10 + 4 - * Public Key (ASCII text) at sec_tag*10 + 5 - * - * Currently PSK, PSK identity and Public Key are not supported. - * - * @param[in] sec_tag SLM security tag of the credential - * @param[in] type TLS credential types - * - * @return Non-negative nRF security tag if successful, - * negative error code if failure. - */ -nrf_sec_tag_t slm_tls_map_sectag(sec_tag_t sec_tag, uint16_t type); - -/** - * @brief Load credential - * - * @param[in] sec_tag TLS reference - * - * @return 0 if successful, negative error code if failure. - */ -int slm_tls_loadcrdl(sec_tag_t sec_tag); - -/** - * @brief Unload credential - * - * @param[in] sec_tag TLS reference - * - * @return 0 if successful, negative error code if failure. - */ -int slm_tls_unloadcrdl(sec_tag_t sec_tag); - -/** @} */ - -#endif /* SLM_NATIVE_TLS_ */ diff --git a/applications/serial_lte_modem/src/slm_ppp.c b/applications/serial_lte_modem/src/slm_ppp.c index 94c26c62009..7199840c832 100644 --- a/applications/serial_lte_modem/src/slm_ppp.c +++ b/applications/serial_lte_modem/src/slm_ppp.c @@ -7,12 +7,17 @@ #include "slm_ppp.h" #include "slm_at_host.h" #include "slm_util.h" -#include +#if defined(CONFIG_SLM_CMUX) +#include "slm_cmux.h" +#endif #include #include +#include +#include #include #include #include +#include #include LOG_MODULE_REGISTER(slm_ppp, CONFIG_SLM_LOG_LEVEL); @@ -23,8 +28,12 @@ LOG_MODULE_REGISTER(slm_ppp, CONFIG_SLM_LOG_LEVEL); */ bool slm_fwd_cgev_notifs; -static const struct device *ppp_uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ppp_uart)); -static int ppp_iface_idx; +#if defined(CONFIG_SLM_CMUX) +BUILD_ASSERT(!DT_NODE_EXISTS(DT_CHOSEN(ncs_slm_ppp_uart)), + "When CMUX is enabled PPP is usable only through it so it cannot have its own UART."); +#else +static const struct device *ppp_uart_dev = DEVICE_DT_GET(DT_CHOSEN(ncs_slm_ppp_uart)); +#endif static struct net_if *ppp_iface; static uint8_t ppp_data_buf[1500]; @@ -35,9 +44,15 @@ static K_THREAD_STACK_DEFINE(ppp_data_passing_thread_stack, KB(2)); static void ppp_data_passing_thread(void*, void*, void*); static struct k_work ppp_restart_work; +static struct k_work ppp_stop_work; static bool ppp_peer_connected; +MODEM_PPP_DEFINE(ppp_module, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + sizeof(ppp_data_buf), sizeof(ppp_data_buf)); + +static struct modem_pipe *ppp_pipe; + /* We use only the default PDP context. */ enum { PDP_CID = 0 }; @@ -64,7 +79,7 @@ static bool open_ppp_sockets(void) ppp_zephyr_dst_addr = (struct sockaddr_ll){ .sll_family = AF_PACKET, - .sll_ifindex = ppp_iface_idx + .sll_ifindex = net_if_get_by_iface(ppp_iface) }; ret = bind(ppp_fds[ZEPHYR_FD_IDX], (const struct sockaddr *)&ppp_zephyr_dst_addr, sizeof(ppp_zephyr_dst_addr)); @@ -98,6 +113,8 @@ static void close_ppp_sockets(void) static bool configure_ppp_link_ip_addresses(struct ppp_context *ctx) { + static uint8_t ppp_ll_addr[PPP_INTERFACE_IDENTIFIER_LEN]; + uint8_t ll_addr_len; char addr4[INET_ADDRSTRLEN]; char addr6[INET6_ADDRSTRLEN]; @@ -111,24 +128,40 @@ static bool configure_ppp_link_ip_addresses(struct ppp_context *ctx) LOG_ERR("No connectivity."); return false; } + if (*addr6) { struct in6_addr in6; - struct ipv6cp_options *const opts = &ctx->ipv6cp.my_options; if (inet_pton(AF_INET6, addr6, &in6) != 1) { return false; } /* The interface identifier is the last 64 bits of the IPv6 address. */ - BUILD_ASSERT(sizeof(in6) >= sizeof(opts->iid)); - /* Setting it doesn't seem to change anything in practice, but this - * is what it's meant for, so fill it anyway. - */ - memcpy(opts->iid, (uint8_t *)(&in6 + 1) - sizeof(opts->iid), sizeof(opts->iid)); + BUILD_ASSERT(sizeof(in6) >= sizeof(ppp_ll_addr)); + ll_addr_len = sizeof(ppp_ll_addr); + memcpy(ppp_ll_addr, (uint8_t *)(&in6 + 1) - ll_addr_len, ll_addr_len); + } else { + /* 00-00-5E-00-53-xx as per RFC 7042, as zephyr/drivers/net/ppp.c does. */ + ll_addr_len = 6; + ppp_ll_addr[0] = 0x00; + ppp_ll_addr[1] = 0x00; + ppp_ll_addr[2] = 0x5E; + ppp_ll_addr[3] = 0x00; + ppp_ll_addr[4] = 0x53; + ppp_ll_addr[5] = sys_rand32_get(); } + net_if_set_link_addr(ppp_iface, ppp_ll_addr, ll_addr_len, NET_LINK_UNKNOWN); + return true; } -static int slm_ppp_start(void) +static int ppp_start_failure(int ret) +{ + close_ppp_sockets(); + net_if_down(ppp_iface); + return ret; +} + +static int ppp_start(void) { int ret; unsigned int mtu; @@ -156,10 +189,25 @@ static int slm_ppp_start(void) } if (!open_ppp_sockets()) { - close_ppp_sockets(); - net_if_down(ppp_iface); - return -ENOTCONN; + return ppp_start_failure(-ENOTCONN); + } + +#if defined(CONFIG_SLM_CMUX) + ppp_pipe = slm_cmux_reserve_ppp_channel(); + /* The pipe opening is managed by CMUX. */ +#endif + + modem_ppp_attach(&ppp_module, ppp_pipe); + +#if !defined(CONFIG_SLM_CMUX) + ret = modem_pipe_open(ppp_pipe); + if (ret) { + LOG_ERR("Failed to open PPP pipe (%d).", ret); + return ppp_start_failure(ret); } +#endif + + net_if_carrier_on(ppp_iface); LOG_INF("PPP started."); @@ -172,25 +220,38 @@ static int slm_ppp_start(void) return 0; } -/** @return Whether PPP is fully started. */ -static bool slm_ppp_is_started(void) +bool slm_ppp_is_running(void) { - return net_if_flag_is_set(ppp_iface, NET_IF_UP) + return net_if_is_carrier_ok(ppp_iface) && ppp_fds[ZEPHYR_FD_IDX] >= 0 && ppp_fds[MODEM_FD_IDX] >= 0; } -static void slm_ppp_stop(void) +static void ppp_stop(void) { - if (!slm_ppp_is_started()) { + if (!slm_ppp_is_running()) { return; } - /* First bring the interface down so that slm_ppp_is_started() + LOG_DBG("Stopping PPP..."); + + /* First bring the carrier down so that slm_ppp_is_running() * returns false right away. This is to prevent trying to stop PPP at the * same time from multiple sources: the original one (e.g. "AT#XPPP=0") * and the data passing thread. The latter attempts to stop PPP when it receives * an error on some of the sockets, which happens when they are closed. */ + net_if_carrier_off(ppp_iface); + +#if !defined(CONFIG_SLM_CMUX) + modem_pipe_close(ppp_pipe); +#endif + + modem_ppp_release(&ppp_module); + +#if defined(CONFIG_SLM_CMUX) + slm_cmux_release_ppp_channel(); +#endif + const int ret = net_if_down(ppp_iface); if (ret) { @@ -213,9 +274,9 @@ static void pdp_ctx_event_handler(uint8_t cid, enum pdn_event event, int reason) k_work_submit_to_queue(&slm_work_q, &ppp_restart_work); break; case PDN_EVENT_DEACTIVATED: - if (slm_ppp_is_started()) { + if (slm_ppp_is_running()) { LOG_INF("Connection down. Stopping PPP."); - slm_ppp_stop(); + ppp_stop(); } else { LOG_DBG("Connection down."); } @@ -311,15 +372,20 @@ static int at_cfun_set_callback(char *buf, size_t len, char *at_cmd) static void ppp_restarter(struct k_work *) { - slm_ppp_stop(); + ppp_stop(); - const int ret = slm_ppp_start(); + const int ret = ppp_start(); if (ret) { LOG_ERR("Failed to start PPP (%d).", ret); } } +static void ppp_stopper(struct k_work *) +{ + ppp_stop(); +} + static void ppp_net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { @@ -336,7 +402,7 @@ static void ppp_net_mgmt_event_handler(struct net_mgmt_event_callback *cb, } ppp_peer_connected = false; /* Also ignore this event when it is received after PPP has been stopped. */ - if (!slm_ppp_is_started()) { + if (!slm_ppp_is_running()) { break; } /* For the peer to be able to successfully reconnect @@ -351,65 +417,92 @@ static void ppp_net_mgmt_event_handler(struct net_mgmt_event_callback *cb, int slm_ppp_init(void) { - static struct net_mgmt_event_callback ppp_net_mgmt_event_cb; - +#if !defined(CONFIG_SLM_CMUX) if (!device_is_ready(ppp_uart_dev)) { return -EAGAIN; } - ppp_iface_idx = net_if_get_by_name(CONFIG_NET_PPP_DRV_NAME); - ppp_iface = net_if_get_by_index(ppp_iface_idx); - if (!ppp_iface) { - LOG_ERR("PPP network interface not found (%d).", ppp_iface_idx); - return -ENODEV; + { + static struct modem_backend_uart ppp_uart_backend; + static uint8_t ppp_uart_backend_receive_buf[sizeof(ppp_data_buf)]; + static uint8_t ppp_uart_backend_transmit_buf[sizeof(ppp_data_buf)]; + + const struct modem_backend_uart_config uart_backend_config = { + .uart = ppp_uart_dev, + .receive_buf = ppp_uart_backend_receive_buf, + .receive_buf_size = sizeof(ppp_uart_backend_receive_buf), + .transmit_buf = ppp_uart_backend_transmit_buf, + .transmit_buf_size = sizeof(ppp_uart_backend_transmit_buf), + }; + + ppp_pipe = modem_backend_uart_init(&ppp_uart_backend, &uart_backend_config); + if (!ppp_pipe) { + return -ENOSYS; + } } +#endif + + ppp_iface = modem_ppp_get_iface(&ppp_module); + net_if_flag_set(ppp_iface, NET_IF_POINTOPOINT); pdn_default_ctx_cb_reg(pdp_ctx_event_handler); - net_mgmt_init_event_callback(&ppp_net_mgmt_event_cb, ppp_net_mgmt_event_handler, - NET_EVENT_PPP_PHASE_RUNNING | NET_EVENT_PPP_PHASE_DEAD); - net_mgmt_add_event_callback(&ppp_net_mgmt_event_cb); + { + static struct net_mgmt_event_callback ppp_net_mgmt_event_cb; + + net_mgmt_init_event_callback(&ppp_net_mgmt_event_cb, ppp_net_mgmt_event_handler, + NET_EVENT_PPP_PHASE_RUNNING | NET_EVENT_PPP_PHASE_DEAD); + net_mgmt_add_event_callback(&ppp_net_mgmt_event_cb); + } k_work_init(&ppp_restart_work, ppp_restarter); + k_work_init(&ppp_stop_work, ppp_stopper); LOG_DBG("PPP initialized."); return 0; } -/* Handles AT#XPPP commands. */ -int handle_at_ppp(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xppp, "AT#XPPP", handle_at_ppp); +static int handle_at_ppp(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int ret; unsigned int op; enum { OP_STOP, - OP_RESTART, + OP_START, OP_COUNT }; if (cmd_type == AT_CMD_TYPE_READ_COMMAND) { - rsp_send("\r\n#XPPP: %u,%u\r\n", slm_ppp_is_started(), ppp_peer_connected); + rsp_send("\r\n#XPPP: %u,%u\r\n", slm_ppp_is_running(), ppp_peer_connected); return 0; } - if (cmd_type != AT_CMD_TYPE_SET_COMMAND - || at_params_valid_count_get(&slm_at_param_list) != 2) { + if (cmd_type != AT_CMD_TYPE_SET_COMMAND || param_count != 2) { return -EINVAL; } - ret = at_params_unsigned_int_get(&slm_at_param_list, 1, &op); + ret = at_params_unsigned_int_get(param_list, 1, &op); if (ret) { return ret; } else if (op >= OP_COUNT) { return -EINVAL; } + const bool is_running = slm_ppp_is_running(); - slm_ppp_stop(); - if (op == OP_RESTART) { - return slm_ppp_start(); + if ((!is_running && op == OP_STOP) || (is_running && op == OP_START)) { + return -EALREADY; } - assert(op == OP_STOP); - return 0; + if (op == OP_START) { + ret = ppp_start(); + } else { + /* Send "OK" first in case stopping PPP results in the CMUX AT channel switching. */ + rsp_send_ok(); + k_work_submit_to_queue(&slm_work_q, &ppp_stop_work); + ret = -SILENT_AT_COMMAND_RET; + } + return ret; } static void ppp_data_passing_thread(void*, void*, void*) @@ -427,7 +520,7 @@ static void ppp_data_passing_thread(void*, void*, void*) if (poll_ret <= 0) { LOG_ERR("Sockets polling failed (%d, %d).", poll_ret, errno); - slm_ppp_stop(); + ppp_stop(); return; } @@ -445,7 +538,7 @@ static void ppp_data_passing_thread(void*, void*, void*) LOG_WRN("Unexpected event 0x%x on %s socket.", revents, ppp_socket_names[src]); } - slm_ppp_stop(); + ppp_stop(); return; } const ssize_t len = recv(fds[src].fd, ppp_data_buf, mtu, MSG_DONTWAIT); @@ -462,8 +555,6 @@ static void ppp_data_passing_thread(void*, void*, void*) void *dst_addr = (dst == MODEM_FD_IDX) ? NULL : &ppp_zephyr_dst_addr; socklen_t addrlen = (dst == MODEM_FD_IDX) ? 0 : sizeof(ppp_zephyr_dst_addr); - LOG_DBG("Forwarding %zd bytes to %s socket.", len, ppp_socket_names[dst]); - send_ret = sendto(fds[dst].fd, ppp_data_buf, len, 0, dst_addr, addrlen); if (send_ret == -1) { LOG_ERR("Failed to send %zd bytes to %s socket (%d).", diff --git a/applications/serial_lte_modem/src/slm_ppp.h b/applications/serial_lte_modem/src/slm_ppp.h index 370e0893f3a..67a1cb06259 100644 --- a/applications/serial_lte_modem/src/slm_ppp.h +++ b/applications/serial_lte_modem/src/slm_ppp.h @@ -15,6 +15,6 @@ extern bool slm_fwd_cgev_notifs; /** @retval 0 on success. */ int slm_ppp_init(void); -int handle_at_ppp(enum at_cmd_type cmd_type); +bool slm_ppp_is_running(void); #endif diff --git a/applications/serial_lte_modem/src/slm_sockopt.h b/applications/serial_lte_modem/src/slm_sockopt.h new file mode 100644 index 00000000000..c0a2ff46bb6 --- /dev/null +++ b/applications/serial_lte_modem/src/slm_sockopt.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef SLM_SOCKOPT_ +#define SLM_SOCKOPT_ + +/** @file slm_sockopt.h + * + * @brief SLM socket options for AT-commands. + * @{ + */ + +/** + * @brief Non-secure socket options for XSOCKETOPT. + */ +enum at_sockopt { + AT_SO_REUSEADDR = 2, + AT_SO_RCVTIMEO = 20, + AT_SO_SNDTIMEO = 21, + AT_SO_SILENCE_ALL = 30, + AT_SO_IP_ECHO_REPLY = 31, + AT_SO_IPV6_ECHO_REPLY = 32, + AT_SO_BINDTOPDN = 40, + AT_SO_RAI_NO_DATA = 50, + AT_SO_RAI_LAST = 51, + AT_SO_RAI_ONE_RESP = 52, + AT_SO_RAI_ONGOING = 53, + AT_SO_RAI_WAIT_MORE = 54, + AT_SO_TCP_SRV_SESSTIMEO = 55, + AT_SO_RAI = 61, +}; + +/** + * @brief Secure socket options for XSSOCKETOPT. + */ +enum at_sec_sockopt { + AT_TLS_HOSTNAME = 2, + AT_TLS_CIPHERSUITE_USED = 4, + AT_TLS_PEER_VERIFY = 5, + AT_TLS_SESSION_CACHE = 12, + AT_TLS_SESSION_CACHE_PURGE = 13, + AT_TLS_DTLS_CID = 14, + AT_TLS_DTLS_CID_STATUS = 15, + AT_TLS_DTLS_HANDSHAKE_TIMEO = 18 +}; + +/** @} */ +#endif diff --git a/applications/serial_lte_modem/src/slm_uart_handler.c b/applications/serial_lte_modem/src/slm_uart_handler.c index e8e5f5cbdcd..fcf409088b6 100644 --- a/applications/serial_lte_modem/src/slm_uart_handler.c +++ b/applications/serial_lte_modem/src/slm_uart_handler.c @@ -13,6 +13,7 @@ #include #include #include "slm_uart_handler.h" +#include "slm_at_host.h" #include LOG_MODULE_REGISTER(slm_uart_handler, CONFIG_SLM_LOG_LEVEL); @@ -20,12 +21,9 @@ LOG_MODULE_REGISTER(slm_uart_handler, CONFIG_SLM_LOG_LEVEL); #define UART_RX_TIMEOUT_US 2000 #define UART_ERROR_DELAY_MS 500 -#define SLM_SYNC_STR "Ready\r\n" - +const struct device *const slm_uart_dev = DEVICE_DT_GET(DT_CHOSEN(ncs_slm_uart)); uint32_t slm_uart_baudrate; -static const struct device *uart_dev = DEVICE_DT_GET(DT_CHOSEN(ncs_slm_uart)); - static struct k_work_delayable rx_process_work; struct rx_buf_t { @@ -61,11 +59,6 @@ static atomic_t recovery_state; K_SEM_DEFINE(tx_done_sem, 0, 1); -slm_uart_rx_callback_t rx_callback_t; - -/* global functions defined in different files */ -int indicate_start(void); - static inline struct rx_buf_t *block_start_get(uint8_t *buf) { size_t block_num; @@ -126,7 +119,7 @@ static int rx_enable(void) return -ENOMEM; } - ret = uart_rx_enable(uart_dev, buf->buf, sizeof(buf->buf), UART_RX_TIMEOUT_US); + ret = uart_rx_enable(slm_uart_dev, buf->buf, sizeof(buf->buf), UART_RX_TIMEOUT_US); if (ret) { LOG_ERR("UART RX enable failed: %d", ret); return ret; @@ -135,7 +128,7 @@ static int rx_enable(void) return 0; } -static void rx_disable(void) +static int slm_uart_rx_disable(void) { int err; @@ -144,14 +137,14 @@ static void rx_disable(void) k_sleep(K_MSEC(10)); } - err = uart_rx_disable(uart_dev); + err = uart_rx_disable(slm_uart_dev); if (err) { LOG_ERR("UART RX disable failed: %d", err); - return; + atomic_set(&recovery_state, RECOVERY_IDLE); + return err; } - /* Wait for disable to complete. */ - k_sleep(K_MSEC(100)); + return 0; } static void rx_recovery(void) @@ -169,7 +162,7 @@ static void rx_recovery(void) } if (atomic_cas(&recovery_state, RECOVERY_ONGOING, RECOVERY_IDLE)) { - LOG_INF("UART RX enabled"); + LOG_DBG("UART RX enabled"); } } @@ -178,35 +171,30 @@ static void rx_process(struct k_work *work) struct rx_event_t rx_event; while (k_msgq_get(&rx_event_queue, &rx_event, K_NO_WAIT) == 0) { - if (rx_callback_t) { - rx_callback_t(rx_event.buf, rx_event.len); - } + slm_at_receive(rx_event.buf, rx_event.len); rx_buf_unref(rx_event.buf); } rx_recovery(); } -static int tx_start(bool indicate) +static int tx_start(void) { uint8_t *buf; - size_t ret; + size_t len; int err; enum pm_device_state state = PM_DEVICE_STATE_OFF; - (void)pm_device_state_get(uart_dev, &state); + pm_device_state_get(slm_uart_dev, &state); if (state != PM_DEVICE_STATE_ACTIVE) { - if (indicate) { - (void)indicate_start(); - } return 1; } - ret = ring_buf_get_claim(&tx_buf, &buf, ring_buf_capacity_get(&tx_buf)); - err = uart_tx(uart_dev, buf, ret, SYS_FOREVER_US); + len = ring_buf_get_claim(&tx_buf, &buf, ring_buf_capacity_get(&tx_buf)); + err = uart_tx(slm_uart_dev, buf, len, SYS_FOREVER_US); if (err) { LOG_ERR("UART TX error: %d", err); - (void)ring_buf_get_finish(&tx_buf, 0); + ring_buf_get_finish(&tx_buf, 0); return err; } @@ -224,23 +212,14 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void switch (evt->type) { case UART_TX_DONE: - err = ring_buf_get_finish(&tx_buf, evt->data.tx.len); - if (err) { - LOG_ERR("UART_TX_DONE failure: %d", err); - } - if (ring_buf_is_empty(&tx_buf) == false) { - (void)tx_start(false); - } else { - k_sem_give(&tx_done_sem); - } - break; case UART_TX_ABORTED: err = ring_buf_get_finish(&tx_buf, evt->data.tx.len); if (err) { - LOG_ERR("UART_TX_ABORTED failure: %d", err); + LOG_ERR("UART_TX_%s failure: %d", + (evt->type == UART_TX_DONE) ? "DONE" : "ABORTED", err); } if (ring_buf_is_empty(&tx_buf) == false) { - (void)tx_start(false); + tx_start(); } else { k_sem_give(&tx_done_sem); } @@ -259,15 +238,15 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void break; case UART_RX_BUF_REQUEST: if (k_msgq_num_free_get(&rx_event_queue) < UART_RX_EVENT_COUNT_FOR_BUF) { - LOG_INF("Disabling UART RX: No event space."); + LOG_WRN("Disabling UART RX: No event space."); break; } buf = rx_buf_alloc(); if (!buf) { - LOG_INF("Disabling UART RX: No free buffers."); + LOG_WRN("Disabling UART RX: No free buffers."); break; } - err = uart_rx_buf_rsp(uart_dev, buf->buf, sizeof(buf->buf)); + err = uart_rx_buf_rsp(slm_uart_dev, buf->buf, sizeof(buf->buf)); if (err) { LOG_WRN("Disabling UART RX: %d", err); rx_buf_unref(buf); @@ -279,7 +258,7 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void } break; case UART_RX_STOPPED: - LOG_WRN("UART_RX_STOPPED (%d)", evt->data.rx_stop.reason); + LOG_DBG("UART_RX_STOPPED (%d)", evt->data.rx_stop.reason); break; case UART_RX_DISABLED: LOG_DBG("UART_RX_DISABLED"); @@ -292,65 +271,13 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void } } -int slm_uart_power_on(void) -{ - int err; - - err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME); - if (err && err != -EALREADY) { - LOG_ERR("Can't resume UART: %d", err); - return err; - } - - k_sleep(K_MSEC(100)); - - (void)atomic_set(&recovery_state, RECOVERY_IDLE); - err = rx_enable(); - if (err) { - return err; - } - - k_sem_give(&tx_done_sem); - (void)tx_start(false); - - return 0; -} - -int slm_uart_power_off(void) -{ - int err; - - rx_disable(); - err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND); - if (err && err != -EALREADY) { - LOG_ERR("Can't suspend UART: %d", err); - } - - /* Write sync str to buffer, so it is send first when we power UART.*/ - (void)slm_uart_tx_write(SLM_SYNC_STR, sizeof(SLM_SYNC_STR)-1, true, false); - - return err; -} - -bool slm_uart_can_context_send(const uint8_t *data, size_t len) -{ - if (!k_is_in_isr()) { - return true; - } - LOG_ERR("FIXME: Attempt to send UART message (of size %u) in ISR.", len); - return false; -} - /* Write the data to tx_buffer and trigger sending. */ -int slm_uart_tx_write(const uint8_t *data, size_t len, bool print_full_debug, bool indicate) +static int slm_uart_tx_write(const uint8_t *data, size_t len) { size_t ret; size_t sent = 0; int err; - if (!slm_uart_can_context_send(data, len)) { - return -EINTR; - } k_mutex_lock(&mutex_tx_put, K_FOREVER); while (sent < len) { ret = ring_buf_put(&tx_buf, data + sent, len - sent); @@ -359,7 +286,7 @@ int slm_uart_tx_write(const uint8_t *data, size_t len, bool print_full_debug, bo } else { /* Buffer full, block and start TX. */ k_sem_take(&tx_done_sem, K_FOREVER); - err = tx_start(indicate); + err = tx_start(); if (err) { LOG_ERR("TX buf overflow, %d dropped. Unable to send: %d", len - sent, @@ -373,7 +300,7 @@ int slm_uart_tx_write(const uint8_t *data, size_t len, bool print_full_debug, bo k_mutex_unlock(&mutex_tx_put); if (k_sem_take(&tx_done_sem, K_NO_WAIT) == 0) { - err = tx_start(indicate); + err = tx_start(); if (err == 1) { k_sem_give(&tx_done_sem); return 0; @@ -386,27 +313,26 @@ int slm_uart_tx_write(const uint8_t *data, size_t len, bool print_full_debug, bo /* TX already in progress. */ } - LOG_HEXDUMP_DBG(data, print_full_debug ? len : MIN(HEXDUMP_LIMIT, len), "TX"); - return 0; } -int slm_uart_handler_init(slm_uart_rx_callback_t callback_t) +static int slm_uart_handler_init(void) { int err; uint32_t start_time; struct uart_config cfg; - if (!device_is_ready(uart_dev)) { + if (!device_is_ready(slm_uart_dev)) { LOG_ERR("UART device not ready"); return -ENODEV; } - err = uart_config_get(uart_dev, &cfg); + err = uart_config_get(slm_uart_dev, &cfg); if (err) { LOG_ERR("uart_config_get: %d", err); return err; } + slm_uart_baudrate = cfg.baudrate; LOG_INF("UART baud: %d d/p/s-bits: %d/%d/%d HWFC: %d", cfg.baudrate, cfg.data_bits, cfg.parity, @@ -415,7 +341,7 @@ int slm_uart_handler_init(slm_uart_rx_callback_t callback_t) /* Wait for the UART line to become valid */ start_time = k_uptime_get_32(); do { - err = uart_err_check(uart_dev); + err = uart_err_check(slm_uart_dev); if (err) { uint32_t now = k_uptime_get_32(); @@ -426,12 +352,11 @@ int slm_uart_handler_init(slm_uart_rx_callback_t callback_t) k_sleep(K_MSEC(10)); } } while (err); - err = uart_callback_set(uart_dev, uart_callback, NULL); + err = uart_callback_set(slm_uart_dev, uart_callback, NULL); if (err) { LOG_ERR("Cannot set callback: %d", err); return -EFAULT; } - rx_callback_t = callback_t; (void)atomic_set(&recovery_state, RECOVERY_IDLE); err = rx_enable(); if (err) { @@ -442,22 +367,17 @@ int slm_uart_handler_init(slm_uart_rx_callback_t callback_t) k_sem_give(&tx_done_sem); - err = slm_uart_tx_write(SLM_SYNC_STR, sizeof(SLM_SYNC_STR)-1, true, false); - if (err) { - return err; - } + /* Flush possibly pending data in case SLM was idle. */ + tx_start(); return 0; } -void slm_uart_handler_uninit(void) +int slm_uart_handler_enable(void) { - int err; - - /* Power off UART module */ - rx_disable(); - err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND); - if (err) { - LOG_WRN("Can't suspend UART: %d", err); - } + return slm_at_set_backend((struct slm_at_backend) { + .start = slm_uart_handler_init, + .send = slm_uart_tx_write, + .stop = slm_uart_rx_disable + }); } diff --git a/applications/serial_lte_modem/src/slm_uart_handler.h b/applications/serial_lte_modem/src/slm_uart_handler.h index 6c18cec8aed..1eda0d35d85 100644 --- a/applications/serial_lte_modem/src/slm_uart_handler.h +++ b/applications/serial_lte_modem/src/slm_uart_handler.h @@ -7,73 +7,22 @@ #ifndef SLM_UART_HANDLER_ #define SLM_UART_HANDLER_ -/**@file slm_uart_handler.h +/** @file slm_uart_handler.h * - * @brief UART handler for serial LTE modem + * @brief pure UART handler for serial LTE modem * @{ */ #include "slm_trap_macros.h" +#include #define UART_RX_MARGIN_MS 10 -#define HEXDUMP_LIMIT 16 - +extern const struct device *const slm_uart_dev; extern uint32_t slm_uart_baudrate; -/**@brief UART RX data callback type. - * - * @param data Received data - * @param len Length of data - */ -typedef void (*slm_uart_rx_callback_t)(const uint8_t *data, size_t len); - -/** - * @brief Switch UART power on. - * - * @retval 0 If the UART was successfully powered on. - * Otherwise, a (negative) error code is returned. - */ -int slm_uart_power_on(void); - -/** - * @brief Switch UART power off. - * - * @retval 0 If the UART was successfully powered off. - * Otherwise, a (negative) error code is returned. - */ -int slm_uart_power_off(void); - -/** @return Whether a UART message can be sent from the current context. */ -bool slm_uart_can_context_send(const uint8_t *data, size_t len); +/** @retval 0 on success. Otherwise, the error code is returned. */ +int slm_uart_handler_enable(void); -/** - * @brief Write the data to TX buffer and trigger sending. - * - * @param data Data to write. - * @param len Length of data. - * @param print_full_debug Print full debug traces. - * @param indicate Can trigger the indication pin. - * - * @retval 0 If the data was successfully written to buffer. - * Otherwise, a (negative) error code is returned. - */ -int slm_uart_tx_write(const uint8_t *data, size_t len, bool print_full_debug, bool indicate); - -/** - * @brief Initialize SLM UART handler for serial LTE modem - * - * @param callback_t Callback function to receive RX data. - * - * @retval 0 If the operation was successful. - * Otherwise, a (negative) error code is returned. - */ -int slm_uart_handler_init(slm_uart_rx_callback_t callback_t); - -/** - * @brief Uninitialize SLM UART handler for serial LTE modem - * - */ -void slm_uart_handler_uninit(void); /** @} */ #endif /* SLM_UART_HANDLER_ */ diff --git a/applications/serial_lte_modem/src/slm_util.c b/applications/serial_lte_modem/src/slm_util.c index 72f1ea0a3fe..245f37214e2 100644 --- a/applications/serial_lte_modem/src/slm_util.c +++ b/applications/serial_lte_modem/src/slm_util.c @@ -4,13 +4,14 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ #include -#include -#include +#include #include #include +#include +#include #include +#include #include "slm_util.h" -#include "slm_at_host.h" LOG_MODULE_REGISTER(slm_util, CONFIG_SLM_LOG_LEVEL); @@ -347,8 +348,7 @@ int util_str_to_int(const char *str_buf, int base, int *output) #define PORT_MAX_SIZE 5 /* 0xFFFF = 65535 */ #define PDN_ID_MAX_SIZE 2 /* 0..10 */ -int util_resolve_host(int cid, const char *host, uint16_t port, int family, - LOG_INSTANCE_PTR_DECLARE(log_inst), struct sockaddr *sa) +int util_resolve_host(int cid, const char *host, uint16_t port, int family, struct sockaddr *sa) { int err; char service[PORT_MAX_SIZE + PDN_ID_MAX_SIZE + 2]; @@ -383,7 +383,7 @@ int util_resolve_host(int cid, const char *host, uint16_t port, int family, } else { errstr = gai_strerror(err); } - LOG_INST_ERR(log_inst, "getaddrinfo() error (%d): %s", err, errstr); + LOG_ERR("getaddrinfo() error (%d): %s", err, errstr); } return err; } diff --git a/applications/serial_lte_modem/src/slm_util.h b/applications/serial_lte_modem/src/slm_util.h index e0309c5d0ba..d46fb5855b7 100644 --- a/applications/serial_lte_modem/src/slm_util.h +++ b/applications/serial_lte_modem/src/slm_util.h @@ -12,15 +12,32 @@ * @brief Utility functions for serial LTE modem * @{ */ +#include "slm_trap_macros.h" +#include +#include #include -#include -#include -#include #include -#include +#include +#include extern struct k_work_q slm_work_q; /* SLM's work queue. */ +/** @return Whether the modem is in the given functional mode. */ +bool slm_is_modem_functional_mode(enum lte_lc_func_mode mode); + +/** @brief Puts the modem in minimal function mode. */ +int slm_power_off_modem(void); + +/** @brief Performs a reset of the SiP. */ +FUNC_NORETURN void slm_reset(void); + +void slm_enter_idle(void); +FUNC_NORETURN void slm_enter_sleep(void); +FUNC_NORETURN void slm_enter_shutdown(void); + +/** @brief Temporarily sets the indicate pin high. */ +int slm_indicate(void); + /** Replacement for @c nrf_modem_at_printf() that cannot be * used so that the AT command interception works properly. */ @@ -162,15 +179,13 @@ int util_str_to_int(const char *str, int base, int *output); * @param[in] host Name or IP address of remote host. * @param[in] port Service port of remote host. * @param[in] family Desired address family for the returned address. - * @param[in] log_inst The log instance of the module calling this function. * @param[out] sa The returned address. * * @retval 0 If the operation was successful. * Otherwise, an errno code or a dns_resolve_status enum value * (defined in `zephyr/net/dns_resolve.h`). */ -int util_resolve_host(int cid, const char *host, uint16_t port, int family, - Z_LOG_INSTANCE_STRUCT *log_inst, struct sockaddr *sa); +int util_resolve_host(int cid, const char *host, uint16_t port, int family, struct sockaddr *sa); /** @} */ #endif /* SLM_UTIL_ */ diff --git a/applications/serial_lte_modem/src/twi/slm_at_twi.c b/applications/serial_lte_modem/src/twi/slm_at_twi.c index d6a434f9185..9416c5db525 100644 --- a/applications/serial_lte_modem/src/twi/slm_at_twi.c +++ b/applications/serial_lte_modem/src/twi/slm_at_twi.c @@ -142,8 +142,8 @@ static int do_twi_write_read(uint16_t index, uint16_t dev_addr, const uint8_t *t return ret; } -/* Handles AT#XTWILS command. */ -int handle_at_twi_list(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtwils, "AT#XTWILS", handle_at_twi_list); +static int handle_at_twi_list(enum at_cmd_type cmd_type, const struct at_param_list *, uint32_t) { int err = -EINVAL; @@ -160,8 +160,10 @@ int handle_at_twi_list(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTWIW commands. */ -int handle_at_twi_write(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtwiw_set, "AT#XTWIW=", handle_at_twi_write); +SLM_AT_CMD_CUSTOM(xtwiw_read, "AT#XTWIW?", handle_at_twi_write); +static int handle_at_twi_write(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t param_count) { int err = -EINVAL; uint16_t index, dev_addr; @@ -170,17 +172,17 @@ int handle_at_twi_write(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - if (at_params_valid_count_get(&slm_at_param_list) != 4) { + if (param_count != 4) { LOG_ERR("Wrong input parameters"); return -EINVAL; } - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &index); + err = at_params_unsigned_short_get(param_list, 1, &index); if (err < 0) { LOG_ERR("Fail to get twi index: %d", err); return err; } ascii_len = TWI_ADDR_LEN + 1; - err = util_string_get(&slm_at_param_list, 2, twi_addr_ascii, &ascii_len); + err = util_string_get(param_list, 2, twi_addr_ascii, &ascii_len); if (err < 0) { LOG_ERR("Fail to get device address"); return err; @@ -188,7 +190,7 @@ int handle_at_twi_write(enum at_cmd_type cmd_type) sscanf(twi_addr_ascii, "%hx", &dev_addr); LOG_DBG("dev_addr: %hx", dev_addr); ascii_len = sizeof(twi_data); - err = util_string_get(&slm_at_param_list, 3, twi_data, &ascii_len); + err = util_string_get(param_list, 3, twi_data, &ascii_len); if (err) { return err; } @@ -206,8 +208,9 @@ int handle_at_twi_write(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTWIR commands. */ -int handle_at_twi_read(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtwir, "AT#XTWIR", handle_at_twi_read); +static int handle_at_twi_read(enum at_cmd_type cmd_type, const struct at_param_list *param_list, + uint32_t) { int err = -EINVAL; uint16_t index, dev_addr, num_read; @@ -216,20 +219,20 @@ int handle_at_twi_read(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &index); + err = at_params_unsigned_short_get(param_list, 1, &index); if (err < 0) { LOG_ERR("Fail to get twi index: %d", err); return err; } ascii_len = TWI_ADDR_LEN + 1; - err = util_string_get(&slm_at_param_list, 2, twi_addr_ascii, &ascii_len); + err = util_string_get(param_list, 2, twi_addr_ascii, &ascii_len); if (err < 0) { LOG_ERR("Fail to get device address: %d", err); return err; } sscanf(twi_addr_ascii, "%hx", &dev_addr); LOG_DBG("dev_addr: %hx", dev_addr); - err = at_params_unsigned_short_get(&slm_at_param_list, 3, &num_read); + err = at_params_unsigned_short_get(param_list, 3, &num_read); if (err < 0) { LOG_ERR("Fail to get bytes to read: %d", err); return err; @@ -254,8 +257,9 @@ int handle_at_twi_read(enum at_cmd_type cmd_type) return err; } -/* Handles AT#XTWIWR commands. */ -int handle_at_twi_write_read(enum at_cmd_type cmd_type) +SLM_AT_CMD_CUSTOM(xtwiwr, "AT#XTWIWR", handle_at_twi_write_read); +static int handle_at_twi_write_read(enum at_cmd_type cmd_type, + const struct at_param_list *param_list, uint32_t) { int err = -EINVAL; uint16_t index, dev_addr, num_read; @@ -264,13 +268,13 @@ int handle_at_twi_write_read(enum at_cmd_type cmd_type) switch (cmd_type) { case AT_CMD_TYPE_SET_COMMAND: - err = at_params_unsigned_short_get(&slm_at_param_list, 1, &index); + err = at_params_unsigned_short_get(param_list, 1, &index); if (err < 0) { LOG_ERR("Fail to get twi index: %d", err); return err; } ascii_len = TWI_ADDR_LEN + 1; - err = util_string_get(&slm_at_param_list, 2, twi_addr_ascii, &ascii_len); + err = util_string_get(param_list, 2, twi_addr_ascii, &ascii_len); if (err < 0) { LOG_ERR("Fail to get device address"); return err; @@ -278,12 +282,12 @@ int handle_at_twi_write_read(enum at_cmd_type cmd_type) sscanf(twi_addr_ascii, "%hx", &dev_addr); LOG_DBG("dev_addr: %hx", dev_addr); ascii_len = sizeof(twi_data); - err = util_string_get(&slm_at_param_list, 3, twi_data, &ascii_len); + err = util_string_get(param_list, 3, twi_data, &ascii_len); if (err) { return err; } LOG_DBG("Data to write: %s", (char *)twi_data); - err = at_params_unsigned_short_get(&slm_at_param_list, 4, &num_read); + err = at_params_unsigned_short_get(param_list, 4, &num_read); if (err < 0) { LOG_ERR("Fail to get twi index: %d", err); return err; diff --git a/applications/zigbee_weather_station/README.rst b/applications/zigbee_weather_station/README.rst index 0dd258d42bb..4773d618cf1 100644 --- a/applications/zigbee_weather_station/README.rst +++ b/applications/zigbee_weather_station/README.rst @@ -62,11 +62,11 @@ LED (LD1): Shows the overall state of the device and its connectivity. The following states are possible: - * ``release`` build type + * ``release`` configuration * Even flashing (red color, 500 ms on/500 ms off) - The device is in the Identify mode (after network commissioning). - * ``debug`` build type + * ``debug`` configuration * Constant light (blue) - The device is connected to a Zigbee network. * Even flashing (red color, 500 ms on/500 ms off) - The device is in the Identify mode (after network commissioning). @@ -91,7 +91,7 @@ Button (SW3): USB port: Used for getting logs from the device. - It is enabled only for the ``debug`` build type of the application. + It is enabled only for the ``debug`` configuration of the application. See the :ref:`zigbee_weather_station_app_select_build_type` section to learn how to select the debug configuration. Configuration @@ -131,39 +131,38 @@ CONFIG_WEATHER_CHECK_PERIOD_SECONDS - How often sensor data is read .. _zigbee_weather_station_app_build_types: -Zigbee weather station build types -================================== +Zigbee weather station configurations +===================================== The Zigbee weather station application does not use a single :file:`prj.conf` file. -Configuration files are provided for different build types, and they are located in the :file:`configuration/thingy53_nrf5340_cpuapp` directory. -Before you start testing the application, you can select one of the build types supported by the application, depending on the building method. +The application includes different configurations, with files for each configuration located in the :file:`configuration/thingy53_nrf5340_cpuapp` directory. +Before you start testing, you can select one of the configurations using the :makevar:`FILE_SUFFIX` variable. -See :ref:`app_build_additions_build_types` and :ref:`modifying_build_types` for more information about this feature of the |NCS|. +See :ref:`app_build_file_suffixes` and :ref:`cmake_options` for more information. -The application supports the following build types: +The application supports the following configurations: -.. list-table:: Zigbee weather station build types +.. list-table:: Zigbee weather station configurations :widths: auto :header-rows: 1 - * - Build type + * - Configuration - File name - Supported board - Description - * - Debug + * - Debug (default) - :file:`prj.conf` - All from `Requirements`_ - - | Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs. - | Used by default if no build type is explicitly selected. + - Debug version of the application; can be used to enable additional features for verifying the application behavior, such as logs. * - Release - :file:`prj_release.conf` - All from `Requirements`_ - Release version of the application; can be used to enable only the necessary application functionalities to optimize its performance. -Logging in the debug build type -------------------------------- +Logging in the debug configuration +---------------------------------- -In the debug build type, the application also uses serial console over USB for logging. +In the debug configuration, the application also uses serial console over USB for logging. Besides initialization logs, the following sets of measurement-related data are logged after a measurements update: * Values measured by sensor. @@ -189,11 +188,11 @@ Building and running .. _zigbee_weather_station_app_select_build_type: -Selecting a build type -====================== +Selecting application configuration +=================================== -Before you start testing the application, you can select one of the :ref:`zigbee_weather_station_app_build_types`, depending on your building method. -See :ref:`modifying_build_types` for detailed steps how to select a build type. +Before you start testing the application, you can select one of the :ref:`zigbee_weather_station_app_build_types`. +See :ref:`cmake_options` for information about how to select a suffixed configuration. .. _zigbee_weather_station_app_testing: @@ -201,9 +200,9 @@ Testing ======= .. Note:: - * Part of the testing procedure assumes you are using the ``debug`` :ref:`build type `, as it provides more feedback with **LED (LD1)** and logs through the USB console. + * Part of the testing procedure assumes you are using the ``debug`` :ref:`configuration `, as it provides more feedback with **LED (LD1)** and logs through the USB console. - These steps related to the ``debug`` build type mention the ``debug`` build type and are not required if you are using the ``release`` build type. + These steps related to the ``debug`` configuration mention the ``debug`` configuration and are not required if you are using the ``release`` configuration. * The provided measurement data values depend on the Thingy:53 device's surrounding conditions. * If you want to capture packets with Wireshark, install `nRF Sniffer for 802.15.4`_ and `configure Wireshark for use with Zigbee `_. @@ -211,7 +210,7 @@ Testing After programming the application to your device, complete the following steps to test it: -1. ``debug`` build type: |connect_generic| +1. ``debug`` configuration: |connect_generic| The connection is needed for gathering logs from the Zigbee weather station application. #. Turn on the :ref:`Zigbee shell ` sample programmed as the network coordinator to one of the compatible development kits. See the :ref:`zigbee_shell_sample_testing` section of the sample to learn how to set it up as a coordinator. @@ -246,7 +245,7 @@ After programming the application to your device, complete the following steps t #. When the device joins the network, **LED (LD1)** lights up with a constant blue color. - Additionally, with the ``debug`` build type and console used for logging, output similar to the following appears: + Additionally, with the ``debug`` configuration and console used for logging, output similar to the following appears: .. code-block:: console diff --git a/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.board b/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.board new file mode 100644 index 00000000000..bb8b988a73e --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.board @@ -0,0 +1,9 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if SOC_NRF54L15_ENGA_CPUAPP + +config BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS + bool "nRF54L15 DK nRF54L15 Application MCU non-secure" + +endif # SOC_NRF54L15_CPUAPP diff --git a/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.defconfig b/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.defconfig new file mode 100644 index 00000000000..ca334c53da1 --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/Kconfig.defconfig @@ -0,0 +1,60 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS + +config BOARD + default "nrf54l15pdk_nrf54l15_cpuapp" + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + depends on BUILD_WITH_TFM + +# TODO: Remove the options bellow when (NCSDK-25023) is done +config NRF_SPU_FLASH_REGION_SIZE + hex + default 0x4000 + # This option does not apply to 54, but we pretend the HW has this limitation + # for now for easier porting. NCSDK-25023 + help + FLASH region size for the NRF_SPU peripheral. For nrf54 the + region size is configurable per-region so this option does + not apply. + +config NRF_SPU_FLASH_REGION_ALIGNMENT + hex + default 0x4000 + # This option does not apply to 54, but we pretend the HW has this limitation + # for now for easier porting. NCSDK-25023 + help + FLASH region size for the NRF_SPU peripheral. For nrf54 the + region size is configurable per-region so this option does + not apply. + +config NRF_SPU_RAM_REGION_SIZE + hex + default 0x2000 + # This HW limitation does not apply to 54, but we pretend + # it does for now for easier porting. NCSDK-25023 + help + RAM region size for the NRF_SPU peripheral. For nrf54 the + region size is configurable per-region so this option does + not apply. + + +config NRF_SPU_RAM_REGION_ALIGNMENT + hex + default 0x1000 + help + RAM regions must be aligned to this value due to SPU HW + limitations. + +endif #BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS diff --git a/boards/arm/nrf54l15pdk_nrf54l15/board.cmake b/boards/arm/nrf54l15pdk_nrf54l15/board.cmake new file mode 100644 index 00000000000..455c93140e2 --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/board.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if(CONFIG_BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS) + board_runner_args(jlink "--device=cortex-m33" "--speed=4000") +endif() + +if(BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS) + set(TFM_PUBLIC_KEY_FORMAT "full") +endif() + +if(CONFIG_TFM_FLASH_MERGED_BINARY) + set_property(TARGET runners_yaml_props_target PROPERTY hex_file tfm_merged.hex) +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/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp.yaml b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp.yaml new file mode 100644 index 00000000000..f68dbf3e5fb --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +identifier: nrf54l15pdk_nrf54l15_cpuapp_ns +name: nRF54l15-PDK-nRF54l15-Application-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 256 +flash: 1524 +supported: + - adc + - gpio + - i2c + - spi + - counter + - watchdog + - adc + - i2s diff --git a/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns-pinctrl.dtsi b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns-pinctrl.dtsi new file mode 100644 index 00000000000..b4b924e90ef --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns-pinctrl.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + uart20_default: uart20_default { + group1 { + psels = , + ; + }; + }; + + uart20_sleep: uart20_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart30_default: uart30_default { + group1 { + psels = , + ; + }; + }; + + uart30_sleep: uart30_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + +}; diff --git a/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns.dts b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns.dts new file mode 100644 index 00000000000..2a0b35c8ac6 --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns.dts @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include +#include "nrf54l15pdk_nrf54l15_cpuapp_ns-pinctrl.dtsi" + +/ { + chosen { + zephyr,console = &uart20; + /* TODO: NCSDK-24862: We don't support configuring RRAM and SRAM + * regions in the DTS file yet. The partition manager configures + * these regions now. + */ + zephyr,shell-uart = &uart20; + zephyr,flash = &rram0; + zephyr,sram = &sram0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + led1: led_1 { + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + led2: led_2 { + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + led3: led_3 { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 0"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1"; + zephyr,code = ; + }; + button2: button_2 { + gpios = <&gpio2 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 2"; + zephyr,code = ; + }; + button3: button_3 { + gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 3"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &led0; + led1 = &led1; + led2 = &led2; + led3 = &led3; + sw0 = &button0; + sw1 = &button1; + sw2 = &button2; + sw3 = &button3; + }; +}; + +&uart20 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart20_default>; + pinctrl-1 = <&uart20_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart30 { + /* Disable so that TF-M can use this UART */ + status = "disabled"; + + current-speed = <115200>; + pinctrl-0 = <&uart30_default>; + pinctrl-1 = <&uart30_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&grtc { + status = "okay"; +}; diff --git a/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns_defconfig b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns_defconfig new file mode 100644 index 00000000000..a664c0e6e3f --- /dev/null +++ b/boards/arm/nrf54l15pdk_nrf54l15/nrf54l15pdk_nrf54l15_cpuapp_ns_defconfig @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF54LX=y +CONFIG_SOC_NRF54L15_ENGA_CPUAPP=y +CONFIG_BOARD_NRF54L15PDK_NRF54L15_CPUAPP_NS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# Don't enable the cache in the non-secure image as it is a +# secure-only peripheral on 54l +CONFIG_CACHE_MANAGEMENT=n +CONFIG_EXTERNAL_CACHE=n + +CONFIG_UART_CONSOLE=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# NCSDK-26634: Rollback protection is not supported yet +CONFIG_TFM_PS_ROLLBACK_PROTECTION=n + +# NCSDK-22600: Built-in keys are not supported yet. +CONFIG_TFM_CRYPTO_BUILTIN_KEYS=n + +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y diff --git a/boards/arm/nrf7002dk_nrf5340/nrf5340_cpuapp_common.dts b/boards/arm/nrf7002dk_nrf5340/nrf5340_cpuapp_common.dts index 8ed4476a906..6a40ea03dfc 100644 --- a/boards/arm/nrf7002dk_nrf5340/nrf5340_cpuapp_common.dts +++ b/boards/arm/nrf7002dk_nrf5340/nrf5340_cpuapp_common.dts @@ -107,6 +107,11 @@ btrf-switch-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; }; + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + /* These aliases are provided for compatibility with samples */ aliases { led0 = &led0; diff --git a/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp.dts b/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp.dts index aaa2d1cb4e6..68053730b8c 100644 --- a/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp.dts +++ b/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp.dts @@ -19,5 +19,20 @@ zephyr,code-partition = &slot0_partition; zephyr,sram-secure-partition = &sram0_s; zephyr,sram-non-secure-partition = &sram0_ns; + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x24>; + max-pwr-5g-low-mcs7 = <0x24>; + max-pwr-5g-mid-mcs0 = <0x2C>; + max-pwr-5g-mid-mcs7 = <0x2C>; + max-pwr-5g-high-mcs0 = <0x34>; + max-pwr-5g-high-mcs7 = <0x34>; }; }; diff --git a/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp_ns.dts b/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp_ns.dts index a88e9d6229c..8df0cc50531 100644 --- a/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp_ns.dts +++ b/boards/arm/nrf7002dk_nrf5340/nrf7002dk_nrf5340_cpuapp_ns.dts @@ -17,10 +17,25 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_ns_partition; zephyr,entropy = &psa_rng; + zephyr,wifi = &nordic_wlan0; }; psa_rng: psa-rng { compatible = "zephyr,psa-crypto-rng"; status = "okay"; }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x24>; + max-pwr-5g-low-mcs7 = <0x24>; + max-pwr-5g-mid-mcs0 = <0x2C>; + max-pwr-5g-mid-mcs7 = <0x2C>; + max-pwr-5g-high-mcs0 = <0x34>; + max-pwr-5g-high-mcs7 = <0x34>; + }; }; diff --git a/boards/arm/nrf7002dk_nrf7001_nrf5340/Kconfig.defconfig b/boards/arm/nrf7002dk_nrf7001_nrf5340/Kconfig.defconfig index 509802ec2db..d20676bc610 100644 --- a/boards/arm/nrf7002dk_nrf7001_nrf5340/Kconfig.defconfig +++ b/boards/arm/nrf7002dk_nrf7001_nrf5340/Kconfig.defconfig @@ -77,6 +77,7 @@ endif # BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF534 config BOARD default "nrf7002dk_nrf7001_nrf5340_cpunet" if BOARD_NRF7002DK_NRF7001_NRF5340_CPUNET -config BOARD_NRF7001 +# Hidden (Internal use only) +config NRF70_2_4G_ONLY bool default y if BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP_NS || BOARD_NRF7002DK_NRF7001_NRF5340_CPUNET diff --git a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf5340_cpuapp_common.dts b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf5340_cpuapp_common.dts index 461a9995c04..845bf60d270 100644 --- a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf5340_cpuapp_common.dts +++ b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf5340_cpuapp_common.dts @@ -107,6 +107,11 @@ btrf-switch-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; }; + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + /* These aliases are provided for compatibility with samples */ aliases { led0 = &led0; diff --git a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp.dts b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp.dts index f806ccaa99f..e4ea8a7a0a9 100644 --- a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp.dts +++ b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp.dts @@ -19,5 +19,14 @@ zephyr,code-partition = &slot0_partition; zephyr,sram-secure-partition = &sram0_s; zephyr,sram-non-secure-partition = &sram0_ns; + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; }; }; diff --git a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp_ns.dts b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp_ns.dts index 483d58f8425..1b2091b5c3c 100644 --- a/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp_ns.dts +++ b/boards/arm/nrf7002dk_nrf7001_nrf5340/nrf7002dk_nrf7001_nrf5340_cpuapp_ns.dts @@ -16,5 +16,14 @@ zephyr,sram = &sram0_ns; zephyr,flash = &flash0; zephyr,code-partition = &slot0_ns_partition; + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; }; }; diff --git a/boards/arm/thingy91x_nrf5340/CMakeLists.txt b/boards/arm/thingy91x_nrf5340/CMakeLists.txt new file mode 100644 index 00000000000..660e27072c5 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if (CONFIG_BOARD_THINGY91X_NRF5340_CPUAPP OR CONFIG_BOARD_THINGY91X_NRF5340_CPUAPP_NS) +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_BOARD_ENABLE_CPUNET nrf5340_cpunet_reset.c) +set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_LIST_DIR}/thingy91x_nrf5340_pm_static.yml CACHE INTERNAL "") +endif() diff --git a/boards/arm/thingy91x_nrf5340/Kconfig b/boards/arm/thingy91x_nrf5340/Kconfig new file mode 100644 index 00000000000..506493e9ca4 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/Kconfig @@ -0,0 +1,62 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_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_CPUNET + bool "Enable 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 + +config DOMAIN_CPUNET_BOARD + string + default "thingy91x_nrf5340_cpunet" if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + 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_rpmsg on the nRF5340_cpunet for + Bluetooth applications. + +endif + +if BOARD_THINGY91X_NRF5340_CPUNET + +# BT_CTLR depends on BT. When BT is enabled we should default to also +# enabling the controller. +config BT_CTLR + default y if BT + +config BT_ECC + default y if BT + +config DOMAIN_CPUAPP_BOARD + string + default "thingy91x_nrf5340_cpuapp" if BOARD_THINGY91X_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. + +endif # BOARD_THINGY91X_NRF5340_CPUNET diff --git a/boards/arm/thingy91x_nrf5340/Kconfig.board b/boards/arm/thingy91x_nrf5340/Kconfig.board new file mode 100644 index 00000000000..a99ba01cdf2 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/Kconfig.board @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +config BOARD_THINGY91X_NRF5340_CPUAPP + bool "nRF5340_APP THINGY91X" + depends on SOC_NRF5340_CPUAPP_QKAA + +config BOARD_THINGY91X_NRF5340_CPUAPP_NS + bool "nRF5340_APP THINGY91X" + depends on SOC_NRF5340_CPUAPP_QKAA + +config BOARD_THINGY91X_NRF5340_CPUNET + bool "nRF5340_NET THINGY91X" + depends on SOC_NRF5340_CPUNET_QKAA diff --git a/boards/arm/thingy91x_nrf5340/Kconfig.defconfig b/boards/arm/thingy91x_nrf5340/Kconfig.defconfig new file mode 100644 index 00000000000..b3595d2ea0e --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/Kconfig.defconfig @@ -0,0 +1,118 @@ +# Thingy:91 X nRF5340 board configuration + +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config BOARD + default "thingy91x_nrf5340_cpuapp" if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_THINGY91X_NRF5340_CPUAPP_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + +# 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_THINGY91X_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_THINGY91X_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +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)) + +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_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config BOARD + default "thingy91x_nrf5340_cpunet" if BOARD_THINGY91X_NRF5340_CPUNET + +config MBOX_NRFX_IPC + default MBOX + +if BOARD_THINGY91X_NRF5340_CPUNET + +config BT_CTLR + default y if BT + +endif # BOARD_THINGY91X_NRF5340_CPUNET + +config USE_SEGGER_RTT + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS || BOARD_THINGY91X_NRF5340_CPUNET + +config RTT_CONSOLE + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS || BOARD_THINGY91X_NRF5340_CPUNET + +if !IS_BOOTLOADER_IMG + +config SECURE_BOOT + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS || BOARD_THINGY91X_NRF5340_CPUNET + +config BOOTLOADER_MCUBOOT + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config NRF53_UPGRADE_NETWORK_CORE + default y if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config UPDATEABLE_IMAGE_NUMBER + default 2 if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS + +config SB_SIGNING_KEY_FILE + default "$(ZEPHYR_NRF_MODULE_DIR)/boards/arm/thingy91x_nrf5340/nsib_signing_key.pem" if BOARD_THINGY91X_NRF5340_CPUAPP || BOARD_THINGY91X_NRF5340_CPUAPP_NS || BOARD_THINGY91X_NRF5340_CPUNET + +endif # !IS_BOOTLOADER_IMG diff --git a/boards/arm/thingy91x_nrf5340/board.cmake b/boards/arm/thingy91x_nrf5340/board.cmake new file mode 100644 index 00000000000..d050affb3c4 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/board.cmake @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if(BOARD_THINGY91X_NRF5340_CPUAPP OR BOARD_THINGY91X_NRF5340_CPUAPP_NS) +board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") +board_runner_args(nrfjprog "--nrf-family=NRF53") +endif() + +if(BOARD_THINGY91X_NRF5340_CPUNET) +board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") +board_runner_args(nrfjprog "--nrf-family=NRF53") +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/thingy91x_nrf5340/nrf5340_cpunet_reset.c b/boards/arm/thingy91x_nrf5340/nrf5340_cpunet_reset.c new file mode 100644 index 00000000000..a79579f16e6 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/nrf5340_cpunet_reset.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(thingy91x_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> +#endif + +static void remoteproc_mgr_config(void) +{ +#if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) && \ + (!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 = BIT(4); +#endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */ +} + +static int remoteproc_mgr_boot(void) +{ + + /* 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_force_off(NRF_RESET, false); + + 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/thingy91x_nrf5340/nrf5340_shared_sram_planning_conf.dts b/boards/arm/thingy91x_nrf5340/nrf5340_shared_sram_planning_conf.dts new file mode 100644 index 00000000000..a3b9276ffd2 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/nrf5340_shared_sram_planning_conf.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* 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/thingy91x_nrf5340/nsib_signing_key.pem b/boards/arm/thingy91x_nrf5340/nsib_signing_key.pem new file mode 100644 index 00000000000..8eaf00ac017 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/nsib_signing_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIG5ZF2/vbga3GvMiYkclanR+w/h1V2Pk5bvkAnMdP54roAoGCCqGSM49 +AwEHoUQDQgAEGdLHchVpe7i/FOajzN1oHfp4sJNI7zuT/KiUEzNhkkiCvePMmH6h +Xc5BTWno2CjcVkHTM6s7zHFVoB9YEI9ZnA== +-----END EC PRIVATE KEY----- diff --git a/boards/arm/thingy91x_nrf5340/pre_dt_board.cmake b/boards/arm/thingy91x_nrf5340/pre_dt_board.cmake new file mode 100644 index 00000000000..b78c7ea6eb0 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/pre_dt_board.cmake @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.dts b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.dts new file mode 100644 index 00000000000..31ad3cbbbdb --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include +#include "thingy91x_nrf5340_cpuapp_common.dts" + +/ { + model = "Nordic Thingy:91 X NRF5340 Application"; + compatible = "nordic,thingy91x-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/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.yaml b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.yaml new file mode 100644 index 00000000000..eb6cc2c5c38 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp.yaml @@ -0,0 +1,20 @@ +identifier: thingy91x_nrf5340_cpuapp +name: Thingy91X-NRF5340-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 diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common-pinctrl.dtsi new file mode 100644 index 00000000000..c0a70d086c4 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common-pinctrl.dtsi @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common.dts b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common.dts new file mode 100644 index 00000000000..5c88b4d6f06 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_common.dts @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "thingy91x_nrf5340_cpuapp_common-pinctrl.dtsi" + +/ { + + 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 14 GPIO_ACTIVE_HIGH>; + label = "Red LED"; + }; + led1: led_1 { + gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + label = "Green LED"; + }; + led2: led_2 { + gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Button 2"; + }; + }; + + zephyr,user { + button1-gpios = <&gpio1 15 (GPIO_PULL_UP | GPIO_OPEN_DRAIN)>; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + led2 = &led2; + sw0 = &button0; + bootloader-led0 = &led0; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + watchdog0 = &wdt0; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uart0 { + status = "disabled"; + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + status = "disabled"; + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +/* This is not the layout that's actually used! It's overridden by Partition Manager. */ +&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"; + reg = <0x00010000 0x40000>; + }; + slot0_ns_partition: partition@50000 { + label = "image-0-nonsecure"; + reg = <0x00050000 0x30000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x40000>; + }; + slot1_ns_partition: partition@c0000 { + label = "image-1-nonsecure"; + reg = <0x000c0000 0x30000>; + }; + /* 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 */ + reg = <0x20000000 DT_SIZE_K(448)>; + }; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + reg = <0x20000000 0x40000>; + }; + + sram0_ns: image_ns@20040000 { + /* Non-Secure image memory */ + reg = <0x20040000 0x30000>; + }; + }; +}; + +/ { + sram0_ns@2007fc00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2007fc00 DT_SIZE_K(1)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_mode0: boot_mode@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + prefix = [08 04]; + checksum = <1>; + }; + }; + }; + + rtt0: rtt_chan0 { + compatible = "segger,rtt-uart"; + status = "okay"; + }; + + chosen { + zephyr,boot-mode = &boot_mode0; + zephyr,console = &rtt0; + zephyr,shell-uart = &rtt0; + zephyr,uart-mcumgr = &rtt0; + zephyr,bt-mon-uart = &rtt0; + zephyr,bt-c2h-uart = &rtt0; + }; +}; + +/* Include partition configuration file */ +#include "nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_defconfig b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_defconfig new file mode 100644 index 00000000000..de293e3cd30 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_defconfig @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_THINGY91X_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 + +CONFIG_PINCTRL=y + +CONFIG_RETENTION=y +CONFIG_RETAINED_MEM=y +CONFIG_RETAINED_MEM_ZEPHYR_RAM=y +CONFIG_RETENTION_BOOT_MODE=y + +CONFIG_SECURE_BOOT_DEBUG_RTT=y diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.dts b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.dts new file mode 100644 index 00000000000..61b486fd6db --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.dts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include +#include "thingy91x_nrf5340_cpuapp_common.dts" + +/ { + model = "Nordic NRF5340 DK NRF5340 Application"; + compatible = "nordic,nrf5340-dk-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + zephyr,entropy = &psa_rng; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; +}; diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.yaml b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.yaml new file mode 100644 index 00000000000..12963b29c8c --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns.yaml @@ -0,0 +1,18 @@ +identifier: thingy91x_nrf5340_cpuapp_ns +name: THINGY91X-NRF5340-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - i2c + - pwm + - watchdog + - usb_cdc + - usb_device + - netif:openthread + - gpio diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns_defconfig b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns_defconfig new file mode 100644 index 00000000000..a93fca2361e --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpuapp_ns_defconfig @@ -0,0 +1,37 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_THINGY91X_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 + +CONFIG_PINCTRL=y + +CONFIG_RETENTION=y +CONFIG_RETAINED_MEM=y +CONFIG_RETAINED_MEM_ZEPHYR_RAM=y +CONFIG_RETENTION_BOOT_MODE=y + +CONFIG_SECURE_BOOT_DEBUG_RTT=y diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.dts b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.dts new file mode 100644 index 00000000000..1d507d2d36d --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include + +/ { + model = "Nordic Thingy:91 X NRF5340 Network"; + compatible = "nordic,thingy91x-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,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + zephyr,code-partition = &slot0_partition; + zephyr,ieee802154 = &ieee802154; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + watchdog0 = &wdt0; + }; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + 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>; + }; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +/* Include shared RAM configuration file */ +#include "nrf5340_shared_sram_planning_conf.dts" diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.yaml b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.yaml new file mode 100644 index 00000000000..eea461d5c62 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet.yaml @@ -0,0 +1,13 @@ +identifier: thingy91x_nrf5340_cpunet +name: Thingy91X-NRF5340-network-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 64 +flash: 256 +supported: + - watchdog + - gpio diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet_defconfig b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet_defconfig new file mode 100644 index 00000000000..df8286df3b5 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_cpunet_defconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUNET_QKAA=y +CONFIG_BOARD_THINGY91X_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 + +CONFIG_PINCTRL=y diff --git a/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_pm_static.yml b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_pm_static.yml new file mode 100644 index 00000000000..18a81a9a7e5 --- /dev/null +++ b/boards/arm/thingy91x_nrf5340/thingy91x_nrf5340_pm_static.yml @@ -0,0 +1,4 @@ +sram_retained_mem: + region: sram_primary + address: 0x2007FC00 + size: 0x400 diff --git a/boards/arm/thingy91x_nrf9151/CMakeLists.txt b/boards/arm/thingy91x_nrf9151/CMakeLists.txt new file mode 100644 index 00000000000..70c0003d848 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/CMakeLists.txt @@ -0,0 +1,12 @@ +# Kconfig - nRF91 Thingy:91 X board configuration +# +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +zephyr_library() +if(CONFIG_BOARD_THINGY91X_NRF9151_NS) + # Use static partition layout to ensure the partition layout remains + # unchanged after DFU. This needs to be made globally available + # because it is used in other CMake files. + set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_LIST_DIR}/thingy91x_pm_static.yml CACHE INTERNAL "") +endif() diff --git a/boards/arm/thingy91x_nrf9151/Kconfig.board b/boards/arm/thingy91x_nrf9151/Kconfig.board new file mode 100644 index 00000000000..00594d681fb --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/Kconfig.board @@ -0,0 +1,14 @@ +# Thingy:91 X nRF9151 board configuration +# +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if SOC_NRF9151_LACA + +config BOARD_THINGY91X_NRF9151 + bool "nRF9151 THINGY91X" + +config BOARD_THINGY91X_NRF9151_NS + bool "nRF9151 THINGY91X non-secure" + +endif # SOC_NRF9151_LACA diff --git a/boards/arm/thingy91x_nrf9151/Kconfig.defconfig b/boards/arm/thingy91x_nrf9151/Kconfig.defconfig new file mode 100644 index 00000000000..6a2790ba4b2 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/Kconfig.defconfig @@ -0,0 +1,125 @@ +# Thingy:91 X nRF9151 board configuration +# +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if BOARD_THINGY91X_NRF9151 || BOARD_THINGY91X_NRF9151_NS + +DT_COMPAT_NORDIC_NRF700X_SPI := nordic,nrf700x-spi +config NRF7002_ON_SPI + def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF700X_SPI)) + +config BOARD + default "thingy91x_nrf9151" + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_THINGY91X_NRF9151_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +config PM_PARTITION_SIZE_TFM_SRAM + hex + default 0xa000 + +endif # BUILD_WITH_TFM + +# 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. + +if BOARD_THINGY91X_NRF9151 && TRUSTED_EXECUTION_SECURE + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif # BOARD_THINGY91X_NRF9151 && TRUSTED_EXECUTION_SECURE + +if BOARD_THINGY91X_NRF9151_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_THINGY91X_NRF9151_NS + +config BT_HCI_VS + default y if BT + +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + +# check if we are building for any bootloader +if !IS_BOOTLOADER_IMG + +config SECURE_BOOT + default y + +config BOOTLOADER_MCUBOOT + default y + +# Do not use these keys for own custom boards! +# These are meant as examples and therefore public. +# The documentation of the nRF Secure Immutable Bootloader and MCUBoot detail on how +# to set up your own keys. + +config SB_SIGNING_KEY_FILE + default "$(ZEPHYR_NRF_MODULE_DIR)/boards/arm/thingy91x_nrf9151/nsib_signing_key.pem" + +config I2C + default y + +config MODEM_ANTENNA + depends on NRF_MODEM_LIB + default y + +if MODEM_ANTENNA + +config MODEM_ANTENNA_AT_MIPIRFFEDEV + default "AT%XMIPIRFFEDEV=1,4,71,198,248" +config MODEM_ANTENNA_AT_MIPIRFFECTRL_INIT + default "AT%XMIPIRFFECTRL=1,0,1,28,248" +config MODEM_ANTENNA_AT_MIPIRFFECTRL_ON + default "AT%XMIPIRFFECTRL=1,1,1,28,56,13,0,0,8,8,715,4,4,770,12,12,829,11,11,863,130,130,892,1,1,939,129,129,978,26,26,1042,8,8,1118,4,4,1270,12,12,1386,14,14,1523,130,130,2200" +config MODEM_ANTENNA_AT_MIPIRFFECTRL_OFF + default "AT%XMIPIRFFECTRL=1,2,1,28,184" +config MODEM_ANTENNA_AT_MIPIRFFECTRL_PWROFF + default "AT%XMIPIRFFECTRL=1,3,1,28,184" +config MODEM_ANTENNA_AT_COEX0 + default "AT\%XCOEX0=1,1,1565,1586" + +endif # MODEM_ANTENNA + +# For on-board regulators +config REGULATOR + default y + +# nPM6001 must be initialized after it is powered from nPM1300 (REGULATOR_NPM1300_INIT_PRIORITY) +config MFD_NPM6001_INIT_PRIORITY + default 87 +config REGULATOR_NPM6001_INIT_PRIORITY + default 88 +config WIFI_INIT_PRIORITY + default 89 + +# GPIO hogs must be initialized after nPM1300 (GPIO_NPM1300_INIT_PRIORITY) +config GPIO_HOGS_INIT_PRIORITY + default 86 + +endif # !IS_BOOTLOADER_IMG +endif # BOARD_THINGY91X_NRF9151 || BOARD_THINGY91X_NRF9151_NS diff --git a/boards/arm/thingy91x_nrf9151/board.cmake b/boards/arm/thingy91x_nrf9151/board.cmake new file mode 100644 index 00000000000..7608f76d2e9 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/board.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +board_runner_args(nrfjprog "--nrf-family=NRF91") +board_runner_args(jlink "--device=nRF9160_xxAA" "--speed=4000") +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/thingy91x_nrf9151/dts/thingy91x_wifi.dtsi b/boards/arm/thingy91x_nrf9151/dts/thingy91x_wifi.dtsi new file mode 100644 index 00000000000..e354d6ff8ba --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/dts/thingy91x_wifi.dtsi @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* enable short range rf */ +&ldsw_rf_fe_sr_en { + /delete-property/ output-low; + output-high; +}; + +/* set pmic_wifi enable signal */ +&ldsw_nPM60_en { + regulator-boot-on; +}; + +/* enable pmic_wifi */ +&pmic_wifi { + status = "okay"; +}; + +/* enable nrf70 */ +&nrf700x { + status = "okay"; +}; + +/ { + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x24>; + max-pwr-5g-low-mcs7 = <0x24>; + max-pwr-5g-mid-mcs0 = <0x2C>; + max-pwr-5g-mid-mcs7 = <0x2C>; + max-pwr-5g-high-mcs0 = <0x34>; + max-pwr-5g-high-mcs7 = <0x34>; + }; +}; diff --git a/boards/arm/thingy91x_nrf9151/nsib_signing_key.pem b/boards/arm/thingy91x_nrf9151/nsib_signing_key.pem new file mode 100644 index 00000000000..1cdd94e99e7 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/nsib_signing_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIBKrNbmwin7w9jkHkephjB2B5WZCVBDr1okDE8ohm5/MoAoGCCqGSM49 +AwEHoUQDQgAEklLqwPelAczeO6/A3ua+D0nrGqwsFxqyq/tMlQ3hmvOFTf7PHYfW +pg0xD4c9cEh4H6MjCplgL/yUcr3eHUazgw== +-----END EC PRIVATE KEY----- diff --git a/boards/arm/thingy91x_nrf9151/pre_dt_board.cmake b/boards/arm/thingy91x_nrf9151/pre_dt_board.cmake new file mode 100644 index 00000000000..b78c7ea6eb0 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/pre_dt_board.cmake @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.dts b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.dts new file mode 100644 index 00000000000..e297bda2c98 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.dts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include +#include "thingy91x_nrf9151_common.dts" + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,wifi = &nordic_wlan0; + }; +}; diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.yaml b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.yaml new file mode 100644 index 00000000000..a1e24f35335 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151.yaml @@ -0,0 +1,12 @@ +identifier: thingy91x_nrf9151 +name: Thingy91X-NRF9151 +type: mcu +arch: arm +toolchain: + - gnuarmemb + - zephyr +ram: 64 +flash: 256 +supported: + - gpio + - i2c diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common-pinctrl.dtsi b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common-pinctrl.dtsi new file mode 100644 index 00000000000..bc79c452e80 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common-pinctrl.dtsi @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + pwm0_default: pwm0_default { + group1 { + psels = , + , + ; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + i2c2_default: i2c2_default { + group1 { + psels = , + ; + }; + }; + + i2c2_sleep: i2c2_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi3_default: spi3_default { + group1 { + psels = , + , + ; + }; + }; + + spi3_sleep: spi3_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; + }; + }; + +}; diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common.dts b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common.dts new file mode 100644 index 00000000000..503ae206024 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_common.dts @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "thingy91x_nrf9151_common-pinctrl.dtsi" +#include +#include + +/ { + model = "Nordic Thingy:91 X nRF9151"; + compatible = "nordic,thingy91x-nrf9151"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + nordic,pm-ext-flash = &flash_ext; + }; + + buttons { + compatible = "gpio-keys"; + + button0: button_0 { + gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Button 1"; + }; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_1 { + gpios = <&gpio0 29 0>; + label = "RGB red channel"; + }; + green_led: led_2 { + gpios = <&gpio0 30 0>; + label = "RGB green channel"; + }; + blue_led: led_3 { + gpios = <&gpio0 31 0>; + label = "RGB blue channel"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + pwm_led1: pwm_led_1 { + pwms = <&pwm0 1 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + pwm_led2: pwm_led_2 { + pwms = <&pwm0 2 PWM_MSEC(8) PWM_POLARITY_NORMAL>; + }; + }; + zephyr,user { + nrf5340-reset-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + }; + + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + + aliases { + sw0 = &button0; + led0 = &red_led; + led1 = &green_led; + led2 = &blue_led; + pwm-led0 = &pwm_led0; + pwm-led1 = &pwm_led1; + pwm-led2 = &pwm_led2; + rgb-pwm = &pwm0; + mcuboot-button0 = &button0; + spi-flash0 = &flash_ext; + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +/* PWM0 is intended for RGB LED control */ +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c2 { + compatible = "nordic,nrf-twim"; + status = "okay"; + clock-frequency = ; + + pinctrl-0 = <&i2c2_default>; + pinctrl-1 = <&i2c2_sleep>; + pinctrl-names = "default", "sleep"; + + bme680: bme680@76 { + status = "disabled"; + compatible = "bosch,bme680"; + reg = <0x76>; + }; + + pmic_main: npm1300@6b { + compatible = "nordic,npm1300"; + host-int-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + pmic-int-pin = <3>; + reg = <0x6b>; + + gpios_pmic: npm1300_gpios { + compatible = "nordic,npm1300-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <5>; + npm13_button: GPIO0 { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + }; + /* GPIO1 switches power to the short range RF front end */ + ldsw_rf_fe_sr_en: GPIO1 { + gpio-hog; + output-low; + gpios = <1 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN | GPIO_PULL_UP)>; + }; + power_switch: GPIO2 { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; + }; + npm60_ready: GPIO4 { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + }; + }; + + regulators { + compatible = "nordic,npm1300-regulator"; + /* Main 3.3 V regulator, enabled by GPIO2 (power switch) */ + reg_3v3: BUCK2 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-gpios = <&gpios_pmic 2 GPIO_ACTIVE_HIGH>; + }; + /* LDO1 is used as a load switch pulling the nPM60 enable line to VSYS */ + ldsw_nPM60_en: LDO1 { + regulator-initial-mode = ; + regulator-allowed-modes = ; + }; + /* LDO2 is used as a load switch for sensor power supply */ + ldsw_sensors: LDO2 { + regulator-initial-mode = ; + regulator-allowed-modes = ; + regulator-boot-on; + }; + }; + + npm1300_charger: charger { + compatible = "nordic,npm1300-charger"; + vbus-limit-microamp = <500000>; + /* Battery specs from LiPol LP803448 datasheet (Dwg. nr. FD_3245_70) */ + term-microvolt = <4200000>; + current-microamp = <675000>; /* 0.5C charging current */ + dischg-limit-microamp = <1340000>; /* Maximum value for PMIC */ + thermistor-cold-millidegrees = <0>; + thermistor-cool-millidegrees = <0>; + thermistor-warm-millidegrees = <45000>; + thermistor-hot-millidegrees = <45000>; + thermistor-ohms = <10000>; + thermistor-beta = <3435>; + charging-enable; + }; + }; + + pmic_wifi: npm6001@70 { + /* refer to thingy91x_wifi.dtsi for enabling wifi */ + status = "disabled"; + + compatible = "nordic,npm6001"; + reg = <0x70>; + + regulators { + compatible = "nordic,npm6001-regulator"; + /* Dedicated 3.3 V regulator for nRF70 */ + reg_wifi: BUCK3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; + regulator-boot-on; + }; + }; + }; + + accel: accelerometer_lp: adxl367@1d { + status = "disabled"; + compatible = "adi,adxl367"; + odr = <3>; + reg = <0x1d>; + int1-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + }; + + magnetometer: bmm150@10 { + status = "disabled"; + compatible = "bosch,bmm150"; + reg = <0x10>; + drdy-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + cs-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>, + <&gpio0 17 GPIO_ACTIVE_LOW>, <&gpio0 10 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + flash_ext: GD25LE255E@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <8000000>; + size = <268435456>; + has-dpd; + t-enter-dpd = <3000>; + t-exit-dpd = <20000>; + sfdp-bfp = [e5 20 f3 ff ff ff ff 0f 44 eb 08 6b 08 3b 42 bb + fe ff ff ff ff ff 00 ff ff ff 42 eb 0c 20 0f 52 + 10 d8 00 ff d4 31 a5 fe 84 df 14 4f ec 62 16 33 + 7a 75 7a 75 04 b3 d5 5c 19 06 14 00 08 50 00 01]; + jedec-id = [c8 60 19]; + }; + + nrf700x: nrf7000@1 { + compatible = "nordic,nrf700x-spi"; + status = "disabled"; + reg = <1>; + spi-max-frequency = ; + + iovdd-ctrl-gpios = <&gpio0 27 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + bucken-gpios = <&gpio0 28 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + host-irq-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + }; + + accelerometer_hp: bmi270@2 { + compatible = "bosch,bmi270"; + status = "disabled"; + reg = <2>; + spi-max-frequency = ; + irq-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + }; + +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + current-speed = <1000000>; + status = "okay"; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +/* This is not the layout that's actually used! It's overridden by Partition Manager. */ +&flash0 { + /* + * For more information, see: + * http://docs.zephyrproject.org/devices/dts/flash_partitions.html + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x10000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x30000>; + }; + slot0_ns_partition: partition@40000 { + label = "image-0-nonsecure"; + reg = <0x00040000 0x40000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x30000>; + }; + slot1_ns_partition: partition@b0000 { + label = "image-1-nonsecure"; + reg = <0x000b0000 0x40000>; + }; + scratch_partition: partition@f0000 { + label = "image-scratch"; + reg = <0x000f0000 0xa000>; + }; + storage_partition: partition@fa000 { + label = "storage"; + reg = <0x000fa000 0x00006000>; + }; + }; +}; + +/ { + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + reg = <0x20000000 DT_SIZE_K(64)>; + }; + + sram0_bsd: image_bsd@20010000 { + /* BSD (shared) memory */ + reg = <0x20010000 DT_SIZE_K(64)>; + }; + + sram0_ns: image_ns@20020000 { + /* Non-Secure image memory */ + reg = <0x20020000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_defconfig b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_defconfig new file mode 100644 index 00000000000..241d76ad00f --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_defconfig @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF91X=y +CONFIG_SOC_NRF9151_LACA=y +CONFIG_BOARD_THINGY91X_NRF9151=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# Enable PINCTRL +CONFIG_PINCTRL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable UARTE +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Disable entropy driver, as it's not yet implemented for nRF9151 +CONFIG_ENTROPY_NRF5_RNG=n diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.dts b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.dts new file mode 100644 index 00000000000..419ae0a76eb --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.dts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/dts-v1/; +#include +#include "thingy91x_nrf9151_common.dts" + +/ { + chosen { + zephyr,flash = &flash0; + zephyr,sram = &sram0_ns; + zephyr,code-partition = &slot0_ns_partition; + zephyr,wifi = &nordic_wlan0; + }; +}; + +/* Disable Zephyr driver for UART1. This port is reserved for modem traces and T-FM logging. + */ +&uart1 { + status = "disabled"; +}; diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.yaml b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.yaml new file mode 100644 index 00000000000..50e6bfcf1d4 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns.yaml @@ -0,0 +1,11 @@ +identifier: thingy91x_nrf9151_ns +name: Thingy91X-nRF9151-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - zephyr +ram: 128 +flash: 256 +supported: + - i2c diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns_defconfig b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns_defconfig new file mode 100644 index 00000000000..c546c45c253 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_nrf9151_ns_defconfig @@ -0,0 +1,47 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +CONFIG_SOC_SERIES_NRF91X=y +CONFIG_SOC_NRF9151_LACA=y +CONFIG_BOARD_THINGY91X_NRF9151_NS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# Enable PINCTRL +CONFIG_PINCTRL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable UARTE +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable I2C +CONFIG_I2C=y + +# Enable SPI +CONFIG_SPI=y + +# Enable Flash +CONFIG_FLASH=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_IDLE_IN_DPD=y + +# Enable sensor (for nPM1300 charger) +CONFIG_SENSOR=y + +# Disable entropy driver, as it's not yet implemented for nRF9151 +CONFIG_ENTROPY_NRF5_RNG=n diff --git a/boards/arm/thingy91x_nrf9151/thingy91x_pm_static.yml b/boards/arm/thingy91x_nrf9151/thingy91x_pm_static.yml new file mode 100644 index 00000000000..e23a3055913 --- /dev/null +++ b/boards/arm/thingy91x_nrf9151/thingy91x_pm_static.yml @@ -0,0 +1,104 @@ +b0: + address: 0x0 + size: 0x8000 + region: flash_primary +b0_container: + address: 0x0 + size: 0x8000 + region: flash_primary + span: [b0] +s0: + address: 0x8000 + size: 0x14000 + span: [mcuboot, s0_pad] + region: flash_primary +s0_pad: + address: 0x8000 + size: 0x200 + share_size: [mcuboot_pad] + region: flash_primary +s0_image: + address: 0x8200 + size: 0x13e00 + span: [mcuboot] + region: flash_primary +mcuboot: + address: 0x8200 + size: 0x13e00 + region: flash_primary +s1: + address: 0x1c000 + size: 0x14000 + span: [s1_pad, s1_image] + region: flash_primary +s1_pad: + address: 0x1c000 + size: 0x200 + region: flash_primary + share_size: [mcuboot_pad] +s1_image: + address: 0x1c200 + size: 0x13e00 + share_size: [mcuboot] + region: flash_primary +mcuboot_primary: + address: 0x30000 + size: 0xD0000 + span: [mcuboot_pad, app, tfm] + region: flash_primary +tfm_secure: + address: 0x30000 + size: 0x8000 + span: [mcuboot_pad, tfm] + region: flash_primary +mcuboot_pad: + address: 0x30000 + size: 0x200 + region: flash_primary +mcuboot_primary_app: + address: 0x30200 + size: 0xcfe00 + span: [tfm, app] + region: flash_primary +app_image: + address: 0x30200 + size: 0xcfe00 + span: [tfm, app] + region: flash_primary +tfm: + address: 0x30200 + size: 0x7e00 + region: flash_primary +tfm_nonsecure: + address: 0x38000 + size: 0xc8000 + span: [app] + region: flash_primary +app: + address: 0x38000 + size: 0xc8000 + region: flash_primary + +external_flash: + device: GD25LB256E + address: 0x0 + size: 0x2000000 + span: [mcuboot_secondary] + region: external_flash +mcuboot_secondary: + device: GD25LB256E + address: 0x0 + size: 0xD0000 + share_size: [mcuboot_primary] + region: external_flash +nonsecure_storage: + device: GD25LB256E + address: 0xD0000 + size: 0x2000 + span: [settings_storage] + region: external_flash +settings_storage: + device: GD25LB256E + address: 0xD0000 + size: 0x2000 + region: external_flash diff --git a/boards/shields/coverage_support/Kconfig.shield b/boards/shields/coverage_support/Kconfig.shield new file mode 100644 index 00000000000..8d1b411b248 --- /dev/null +++ b/boards/shields/coverage_support/Kconfig.shield @@ -0,0 +1,7 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +config SHIELD_COVERAGE_SUPPORT + def_bool $(shields_list_contains,coverage_support) diff --git a/boards/shields/coverage_support/coverage_support.conf b/boards/shields/coverage_support/coverage_support.conf new file mode 100644 index 00000000000..1164b4fc066 --- /dev/null +++ b/boards/shields/coverage_support/coverage_support.conf @@ -0,0 +1,19 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_FORCE_COVERAGE=y +CONFIG_COVERAGE_GCOV=y +CONFIG_COVERAGE_GCOV_HEAP_SIZE=0 +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_TEST_EXTRA_STACK_SIZE=2048 +CONFIG_ISR_STACK_SIZE=5120 +CONFIG_IDLE_STACK_SIZE=4096 +CONFIG_PRIVILEGED_STACK_SIZE=2048 +CONFIG_SHELL_STACK_SIZE=4096 +CONFIG_ZTEST_STACK_SIZE=4096 +CONFIG_IPM_CONSOLE_STACK_SIZE=8092 +CONFIG_IPC_SERVICE_BACKEND_ICMSG_WQ_STACK_SIZE=4096 +CONFIG_SIZE_OPTIMIZATIONS=y diff --git a/boards/shields/coverage_support/coverage_support.overlay b/boards/shields/coverage_support/coverage_support.overlay new file mode 100644 index 00000000000..33c2beb2456 --- /dev/null +++ b/boards/shields/coverage_support/coverage_support.overlay @@ -0,0 +1,4 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ diff --git a/boards/shields/nrf7002eb/nrf7002eb.overlay b/boards/shields/nrf7002eb/nrf7002eb.overlay index 7a66f2d646e..8181584c0f2 100644 --- a/boards/shields/nrf7002eb/nrf7002eb.overlay +++ b/boards/shields/nrf7002eb/nrf7002eb.overlay @@ -5,6 +5,31 @@ #include #include "nrf7002eb_coex.overlay" +/ { + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + + chosen { + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x34>; + max-pwr-5g-low-mcs7 = <0x34>; + max-pwr-5g-mid-mcs0 = <0x34>; + max-pwr-5g-mid-mcs7 = <0x34>; + max-pwr-5g-high-mcs0 = <0x30>; + max-pwr-5g-high-mcs7 = <0x30>; + }; +}; + &edge_connector_spi { status = "okay"; diff --git a/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151.overlay b/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151_ns.overlay b/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151_ns.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek/boards/nrf9151dk_nrf9151_ns.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek/nrf7002ek.overlay b/boards/shields/nrf7002ek/nrf7002ek.overlay index f1de896fb01..e5e03e0ec76 100644 --- a/boards/shields/nrf7002ek/nrf7002ek.overlay +++ b/boards/shields/nrf7002ek/nrf7002ek.overlay @@ -5,6 +5,31 @@ #include #include "nrf7002ek_coex.overlay" +/ { + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + + chosen { + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x34>; + max-pwr-5g-low-mcs7 = <0x34>; + max-pwr-5g-mid-mcs0 = <0x34>; + max-pwr-5g-mid-mcs7 = <0x34>; + max-pwr-5g-high-mcs0 = <0x30>; + max-pwr-5g-high-mcs7 = <0x30>; + }; +}; + &arduino_spi { status = "okay"; diff --git a/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151.overlay b/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151_ns.overlay b/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151_ns.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek_nrf7000/boards/nrf9151dk_nrf9151_ns.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek_nrf7000/nrf7002ek_nrf7000.overlay b/boards/shields/nrf7002ek_nrf7000/nrf7002ek_nrf7000.overlay index 6363b39d413..feb9fd44d72 100644 --- a/boards/shields/nrf7002ek_nrf7000/nrf7002ek_nrf7000.overlay +++ b/boards/shields/nrf7002ek_nrf7000/nrf7002ek_nrf7000.overlay @@ -5,6 +5,31 @@ #include #include "nrf7002ek_nrf7000_coex.overlay" +/ { + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + + chosen { + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x34>; + max-pwr-5g-low-mcs7 = <0x34>; + max-pwr-5g-mid-mcs0 = <0x34>; + max-pwr-5g-mid-mcs7 = <0x34>; + max-pwr-5g-high-mcs0 = <0x30>; + max-pwr-5g-high-mcs7 = <0x30>; + }; +}; + &arduino_spi { status = "okay"; diff --git a/boards/shields/nrf7002ek_nrf7001/Kconfig.shield b/boards/shields/nrf7002ek_nrf7001/Kconfig.shield index 35755c3630f..f157e020845 100644 --- a/boards/shields/nrf7002ek_nrf7001/Kconfig.shield +++ b/boards/shields/nrf7002ek_nrf7001/Kconfig.shield @@ -6,6 +6,6 @@ config SHIELD_NRF7002EK_NRF7001 def_bool $(shields_list_contains,nrf7002ek_nrf7001) -config BOARD_NRF7001 +config NRF70_2_4G_ONLY bool default y if SHIELD_NRF7002EK_NRF7001 diff --git a/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151.overlay b/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151_ns.overlay b/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151_ns.overlay new file mode 100644 index 00000000000..7ebbb062c19 --- /dev/null +++ b/boards/shields/nrf7002ek_nrf7001/boards/nrf9151dk_nrf9151_ns.overlay @@ -0,0 +1,6 @@ +/* Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include diff --git a/boards/shields/nrf7002ek_nrf7001/nrf7002ek_nrf7001.overlay b/boards/shields/nrf7002ek_nrf7001/nrf7002ek_nrf7001.overlay index c25d28d63a0..7d2810c7926 100644 --- a/boards/shields/nrf7002ek_nrf7001/nrf7002ek_nrf7001.overlay +++ b/boards/shields/nrf7002ek_nrf7001/nrf7002ek_nrf7001.overlay @@ -5,6 +5,31 @@ #include #include "nrf7002ek_nrf7001_coex.overlay" +/ { + nordic_wlan0: nordic_wlan0 { + compatible = "nordic,wlan0"; + status = "okay"; + }; + + chosen { + zephyr,wifi = &nordic_wlan0; + }; + + nrf70_tx_power_ceiling: nrf70_tx_power_ceiling_node { + status = "okay"; + compatible = "nordic,nrf700x-tx-power-ceiling"; + max-pwr-2g-dsss = <0x54>; + max-pwr-2g-mcs0 = <0x40>; + max-pwr-2g-mcs7 = <0x40>; + max-pwr-5g-low-mcs0 = <0x34>; + max-pwr-5g-low-mcs7 = <0x34>; + max-pwr-5g-mid-mcs0 = <0x34>; + max-pwr-5g-mid-mcs7 = <0x34>; + max-pwr-5g-high-mcs0 = <0x30>; + max-pwr-5g-high-mcs7 = <0x30>; + }; +}; + &arduino_spi { status = "okay"; diff --git a/cmake/extensions.cmake b/cmake/extensions.cmake index a67cbe1fcab..ce13e657739 100644 --- a/cmake/extensions.cmake +++ b/cmake/extensions.cmake @@ -101,12 +101,12 @@ endfunction() # Convenience macro to add configuration overlays to child image. macro(add_overlay_config image overlay_file) - add_overlay(${image} ${overlay_file} OVERLAY_CONFIG) + add_overlay(${image} ${overlay_file} EXTRA_CONF_FILE) endmacro() # Convenience macro to add device tree overlays to child image. macro(add_overlay_dts image overlay_file) - add_overlay(${image} ${overlay_file} DTC_OVERLAY_FILE) + add_overlay(${image} ${overlay_file} EXTRA_DTC_OVERLAY_FILE) endmacro() # Add a partition manager configuration file to the build. @@ -231,47 +231,84 @@ Please provide one of following: CONF_FILES") if(NCS_FILE_PM) set(PM_FILE_PREFIX pm_static) - # Prepare search for pm_static_board@ver_build.yml - zephyr_build_string(filename - BOARD ${ZEPHYR_FILE_BOARD} - BOARD_REVISION ${ZEPHYR_FILE_BOARD_REVISION} - BUILD ${ZEPHYR_FILE_BUILD} - ) - set(filename_list ${PM_FILE_PREFIX}_${filename}) + if(DEFINED FILE_SUFFIX) + # Prepare search for pm_static_board@ver_suffix.yml + zephyr_build_string(filename + BOARD ${ZEPHYR_FILE_BOARD} + BOARD_REVISION ${ZEPHYR_FILE_BOARD_REVISION} + ) + set(filename_list ${PM_FILE_PREFIX}_${filename}) - # Prepare search for pm_static_board_build.yml - zephyr_build_string(filename - BOARD ${ZEPHYR_FILE_BOARD} - BUILD ${ZEPHYR_FILE_BUILD} - ) - list(APPEND filename_list ${PM_FILE_PREFIX}_${filename}) + # Prepare search for pm_static_board_suffix.yml + zephyr_build_string(filename + BOARD ${ZEPHYR_FILE_BOARD} + ) + list(APPEND filename_list ${PM_FILE_PREFIX}_${filename}) - # Prepare search for pm_static_build.yml - # Note that BOARD argument is used to position suffix accordingly - zephyr_build_string(filename - BOARD ${ZEPHYR_FILE_BUILD} - ) - list(APPEND filename_list ${PM_FILE_PREFIX}_${filename}) + list(APPEND filename_list ${PM_FILE_PREFIX}) + else() + # Prepare search for pm_static_board@ver_build.yml + zephyr_build_string(filename + BOARD ${ZEPHYR_FILE_BOARD} + BOARD_REVISION ${ZEPHYR_FILE_BOARD_REVISION} + BUILD ${ZEPHYR_FILE_BUILD} + ) + set(filename_list ${PM_FILE_PREFIX}_${filename}) + + # Prepare search for pm_static_board_build.yml + zephyr_build_string(filename + BOARD ${ZEPHYR_FILE_BOARD} + BUILD ${ZEPHYR_FILE_BUILD} + ) + list(APPEND filename_list ${PM_FILE_PREFIX}_${filename}) + + # Prepare search for pm_static_build.yml + # Note that BOARD argument is used to position suffix accordingly + zephyr_build_string(filename + BOARD ${ZEPHYR_FILE_BUILD} + ) + list(APPEND filename_list ${PM_FILE_PREFIX}_${filename}) + + # Prepare search for pm_static.yml + list(APPEND filename_list ${PM_FILE_PREFIX}) + endif() - # Prepare search for pm_static.yml - list(APPEND filename_list ${PM_FILE_PREFIX}) list(REMOVE_DUPLICATES filename_list) foreach(filename ${filename_list}) if(DEFINED NCS_FILE_DOMAIN) - if(EXISTS ${NCS_FILE_CONF_FILES}/${filename}_${NCS_FILE_DOMAIN}.yml) - set(${NCS_FILE_PM} ${NCS_FILE_CONF_FILES}/${filename}_${NCS_FILE_DOMAIN}.yml PARENT_SCOPE) - break() + if(DEFINED FILE_SUFFIX) + set(filename_check ${NCS_FILE_CONF_FILES}/${filename}_${NCS_FILE_DOMAIN}.yml) + zephyr_file_suffix(filename_check SUFFIX ${FILE_SUFFIX}) + + if(EXISTS ${filename_check}) + set(${NCS_FILE_PM} ${filename_check} PARENT_SCOPE) + break() + endif() + + else() + if(EXISTS ${NCS_FILE_CONF_FILES}/${filename}_${NCS_FILE_DOMAIN}.yml) + set(${NCS_FILE_PM} ${NCS_FILE_CONF_FILES}/${filename}_${NCS_FILE_DOMAIN}.yml PARENT_SCOPE) + break() + endif() endif() endif() - if(EXISTS ${NCS_FILE_CONF_FILES}/${filename}.yml) - set(${NCS_FILE_PM} ${NCS_FILE_CONF_FILES}/${filename}.yml PARENT_SCOPE) - break() + if(DEFINED FILE_SUFFIX) + set(filename_check ${NCS_FILE_CONF_FILES}/${filename}.yml) + zephyr_file_suffix(filename_check SUFFIX ${FILE_SUFFIX}) + if(EXISTS ${filename_check}) + set(${NCS_FILE_PM} ${filename_check} PARENT_SCOPE) + break() + endif() + else() + if(EXISTS ${NCS_FILE_CONF_FILES}/${filename}.yml) + set(${NCS_FILE_PM} ${NCS_FILE_CONF_FILES}/${filename}.yml PARENT_SCOPE) + break() + endif() endif() endforeach() endif() - endfunction() # diff --git a/cmake/mesh_dfu_metadata.cmake b/cmake/mesh_dfu_metadata.cmake new file mode 100644 index 00000000000..e3174278449 --- /dev/null +++ b/cmake/mesh_dfu_metadata.cmake @@ -0,0 +1,37 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +find_package(Python3 REQUIRED) + +function(mesh_dfu_metadata) + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/dfu_application.zip_ble_mesh_metadata.json + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_NRF_MODULE_DIR}/scripts/bluetooth/mesh/mesh_dfu_metadata.py + --bin-path ${PROJECT_BINARY_DIR} + DEPENDS + ${PROJECT_BINARY_DIR}/dfu_application.zip + ) + + add_custom_target( + parse_mesh_metadata + ALL + DEPENDS ${PROJECT_BINARY_DIR}/dfu_application.zip_ble_mesh_metadata.json + ) + + add_custom_target( + # Prints already generated metadata + ble_mesh_dfu_metadata + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_NRF_MODULE_DIR}/scripts/bluetooth/mesh/mesh_dfu_metadata.py + --bin-path ${PROJECT_BINARY_DIR} + --print-metadata + COMMAND_EXPAND_LISTS + ) + +endfunction() diff --git a/cmake/multi_image.cmake b/cmake/multi_image.cmake index 0bcfa52245b..d52d02147ef 100644 --- a/cmake/multi_image.cmake +++ b/cmake/multi_image.cmake @@ -341,7 +341,13 @@ function(add_child_image_from_source) # Check for configuration fragment. The contents of these are appended # to the project configuration, as opposed to the CONF_FILE which is used # as the base configuration. - if(NOT "${CONF_FILE_BUILD_TYPE}" STREQUAL "") + if(DEFINED ${ACI_NAME}_FILE_SUFFIX) + # Child/parent image does not support a prefix for the main application, therefore only + # use child image configuration with suffixes if specifically commanded with an argument + # targeting this child image + set(child_image_conf_fragment ${ACI_CONF_DIR}/${ACI_NAME}.conf) + zephyr_file_suffix(child_image_conf_fragment SUFFIX ${${ACI_NAME}_FILE_SUFFIX}) + elseif(NOT "${CONF_FILE_BUILD_TYPE}" STREQUAL "") set(child_image_conf_fragment ${ACI_CONF_DIR}/${ACI_NAME}_${CONF_FILE_BUILD_TYPE}.conf) else() set(child_image_conf_fragment ${ACI_CONF_DIR}/${ACI_NAME}.conf) diff --git a/cmake/partition_manager.cmake b/cmake/partition_manager.cmake index 06e2b858550..0a1c611d123 100644 --- a/cmake/partition_manager.cmake +++ b/cmake/partition_manager.cmake @@ -26,6 +26,10 @@ endmacro() # Load static configuration if found. # Try user defined file first, then file found in configuration directory, # finally file from board directory. +if(SYSBUILD) + zephyr_get(PM_STATIC_YML_FILE SYSBUILD GLOBAL) +endif() + if(DEFINED PM_STATIC_YML_FILE) string(CONFIGURE "${PM_STATIC_YML_FILE}" user_def_pm_static) endif() @@ -206,6 +210,14 @@ elseif (DEFINED CONFIG_SOC_NRF5340_CPUAPP) set(otp_size 764) # 191 * 4 endif() +if (DEFINED CONFIG_SOC_SERIES_NRF54LX) + set(soc_nvs_controller rram_controller) + set(soc_nvs_controller_driver_kc CONFIG_SOC_FLASH_NRF_RRAM) +else() + set(soc_nvs_controller flash_controller) + set(soc_nvs_controller_driver_kc CONFIG_SOC_FLASH_NRF) +endif() + add_region( NAME sram_primary SIZE ${CONFIG_PM_SRAM_SIZE} @@ -229,8 +241,8 @@ add_region( SIZE ${flash_size} BASE ${CONFIG_FLASH_BASE_ADDRESS} PLACEMENT complex - DEVICE flash_controller - DEFAULT_DRIVER_KCONFIG CONFIG_SOC_FLASH_NRF + DEVICE ${soc_nvs_controller} + DEFAULT_DRIVER_KCONFIG ${soc_nvs_controller_driver_kc} ) dt_chosen(ext_flash_dev PROPERTY nordic,pm-ext-flash) diff --git a/cmake/sysbuild/partition_manager.cmake b/cmake/sysbuild/partition_manager.cmake index af3c174b37b..00d2782be5d 100644 --- a/cmake/sysbuild/partition_manager.cmake +++ b/cmake/sysbuild/partition_manager.cmake @@ -498,6 +498,15 @@ foreach(d APP ${PM_DOMAINS}) set(otp_size 764) # 191 * 4 endif() + sysbuild_get(${image_name}_CONFIG_SOC_SERIES_NRF54LX IMAGE ${image_name} VAR CONFIG_SOC_SERIES_NRF54LX KCONFIG) + if(${image_name}_CONFIG_SOC_SERIES_NRF54LX) + set(soc_nvs_controller rram_controller) + set(soc_nvs_controller_driver_kc CONFIG_SOC_FLASH_NRF_RRAM) + else() + set(soc_nvs_controller flash_controller) + set(soc_nvs_controller_driver_kc CONFIG_SOC_FLASH_NRF) + endif() + add_region( NAME sram_primary SIZE ${${image_name}_CONFIG_PM_SRAM_SIZE} @@ -525,8 +534,8 @@ foreach(d APP ${PM_DOMAINS}) SIZE ${flash_size} BASE ${${image_name}_CONFIG_FLASH_BASE_ADDRESS} PLACEMENT complex - DEVICE flash_controller - DEFAULT_DRIVER_KCONFIG CONFIG_SOC_FLASH_NRF + DEVICE ${soc_nvs_controller} + DEFAULT_DRIVER_KCONFIG ${soc_nvs_controller_driver_kc} DOMAIN ${d} ) diff --git a/cmake/version.cmake b/cmake/version.cmake index 5dab2f7be99..4249498ea42 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -1,7 +1,5 @@ math(EXPR NCS_VERSION_CODE "(${NCS_VERSION_MAJOR} << 16) + (${NCS_VERSION_MINOR} << 8) + (${NCS_VERSION_PATCH})") - -# to_hex is made available by ${ZEPHYR_BASE}/cmake/hex.cmake -to_hex(${NCS_VERSION_CODE} NCS_VERSION_NUMBER) +math(EXPR NCS_VERSION_NUMBER ${NCS_VERSION_CODE} OUTPUT_FORMAT HEXADECIMAL) if(DEFINED BUILD_VERSION) set(ncs_banner_version BUILD_VERSION) diff --git a/doc/_extensions/manifest_revisions_table.py b/doc/_extensions/manifest_revisions_table.py index 28008f88725..54e101ea1d6 100644 --- a/doc/_extensions/manifest_revisions_table.py +++ b/doc/_extensions/manifest_revisions_table.py @@ -63,10 +63,27 @@ def rev_url(base_url: str, rev: str) -> str: URL for the revision. """ + # remove .git from base_url, if present + base_url = base_url.split(".git")[0] + + if "github.com" in base_url: + commit_fmt = base_url + "/commit/{rev}" + tag_fmt = base_url + "/releases/tag/{rev}" + elif "projecttools.nordicsemi.no" in base_url: + m = re.match(r"^(.*)/scm/(.*)/(.*)$", base_url) + if not m: + raise ExtensionError(f"Invalid base URL: {base_url}") + + base_url = f"{m.group(1)}/projects/{m.group(2)}/repos/{m.group(3)}" + commit_fmt = base_url + "/commits/{rev}" + tag_fmt = commit_fmt + else: + raise ExtensionError(f"Unsupported SCM: {base_url}") + if re.match(r"^[0-9a-f]{40}$", rev): - return f"{base_url}/commit/{rev}" + return commit_fmt.format(rev=rev) - return f"{base_url}/releases/tag/{rev}" + return tag_fmt.format(rev=rev) def run(self) -> List[nodes.Element]: # parse show-first option diff --git a/doc/_scripts/software_maturity/software_maturity_features.yaml b/doc/_scripts/software_maturity/software_maturity_features.yaml index c461abd91ee..00ce3cd8905 100644 --- a/doc/_scripts/software_maturity/software_maturity_features.yaml +++ b/doc/_scripts/software_maturity/software_maturity_features.yaml @@ -18,9 +18,12 @@ top_table: features: sidewalk: Sidewalk over BLE: SIDEWALK && SIDEWALK_LINK_MASK_BLE - Sidewalk over FSK: SIDEWALK && SIDEWALK_LINK_MASK_FSK - Sidewalk over LORA: SIDEWALK && SIDEWALK_LINK_MASK_LORA + Sidewalk over FSK: SIDEWALK && CONFIG_SIDEWALK_SUBGHZ_SUPPORT + Sidewalk over LORA: SIDEWALK && CONFIG_SIDEWALK_SUBGHZ_SUPPORT Sidewalk - OTA DFU over Bluetooth LE: SIDEWALK && SIDEWALK_DFU_SERVICE_BLE + Sidewalk on-device certification: SIDEWALK + Sidewalk Multi-link + Auto-connect: SIDEWALK && CONFIG_SIDEWALK_SUBGHZ_SUPPORT + Sidewalk File Transfer (FUOTA): SIDEWALK && SIDEWALK_FILE_TRANSFER bluetooth: Bluetooth LE Peripheral/Central: BT_CTLR && (BT_CENTRAL || BT_PERIPHERAL) LLPM: BT_CTLR_SDC_LLPM @@ -90,6 +93,41 @@ features: - SHIELD_NRF7002EB - BOARD_NRF7002DK_NRF5340_CPUAPP - BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP + SoftAP Mode: + rule: WIFI_NRF700X && NRF700X_AP_MODE && WPA_SUPP_AP + boards_and_shields: + - SHIELD_NRF7002EK + - SHIELD_NRF7002EK_NRF7000 + - SHIELD_NRF7002EK_NRF7001 + - SHIELD_NRF7002EB + - BOARD_NRF7002DK_NRF5340_CPUAPP + - BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP + Monitor Mode: + rule: WIFI_NRF700X && NRF700X_RAW_DATA_RX + boards_and_shields: + - SHIELD_NRF7002EK + - SHIELD_NRF7002EK_NRF7000 + - SHIELD_NRF7002EK_NRF7001 + - SHIELD_NRF7002EB + - BOARD_NRF7002DK_NRF5340_CPUAPP + - BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP + TX injection Mode: + rule: WIFI_NRF700X && NRF700X_RAW_DATA_TX + boards_and_shields: + - SHIELD_NRF7002EK + - SHIELD_NRF7002EK_NRF7000 + - SHIELD_NRF7002EK_NRF7001 + - SHIELD_NRF7002EB + - BOARD_NRF7002DK_NRF5340_CPUAPP + - BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP + Promiscuous Mode: + rule: WIFI_NRF700X && NRF700X_PROMISC_DATA_RX + boards_and_shields: + - SHIELD_NRF7002EK + - SHIELD_NRF7002EK_NRF7001 + - SHIELD_NRF7002EB + - BOARD_NRF7002DK_NRF5340_CPUAPP + - BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP trusted_firmware_m: Minimal Build: BUILD_WITH_TFM && TFM_PROFILE_TYPE_MINIMAL Full build: BUILD_WITH_TFM && TFM_PROFILE_TYPE_NOT_SET && NRF_SECURITY @@ -99,6 +137,8 @@ features: Immutable Bootloader as part of build: SECURE_BOOT hw_unique_key: Key Derivation from Hardware Unique Key: HW_UNIQUE_KEY + trusted_storage: + Trusted storage implements the PSA Certified Secure Storage APIs without TF-M: TRUSTED_STORAGE power_management: nPM1100: REGULATOR_NPM1100 nPM1300: MFD_NPM1300 diff --git a/doc/_utils/redirects.py b/doc/_utils/redirects.py index 1ef89f37d61..7c9a9615cd1 100644 --- a/doc/_utils/redirects.py +++ b/doc/_utils/redirects.py @@ -20,6 +20,10 @@ ("introduction", "index"), ("app_boards", "config_and_build/board_support"), ("app_dev/board_support/index", "config_and_build/board_support"), + ("config_and_build/board_support", "config_and_build/board_support/index"), + ("config_and_build/output_build_files", "config_and_build/configuring_app/output_build_files"), + ("config_and_build/pin_control", "config_and_build/configure_app/hardware/pin_control"), + ("config_and_build/use_gpio_pin_directly", "config_and_build/configure_app/hardware/use_gpio_pin_directly"), ("ug_bootloader", "config_and_build/bootloaders_and_dfu/bootloader"), ("app_dev/bootloaders_and_dfu/bootloader", "config_and_build/bootloaders_and_dfu/bootloader"), ("app_dev/bootloaders_and_dfu/bootloader", "config_and_build/bootloaders/bootloader"), @@ -54,6 +58,7 @@ ("app_dev/pin_control/index", "device_guides/pin_control"), ("ug_unity_testing", "test_and_optimize/testing_unity_cmock"), ("app_dev/testing_unity_cmock/index", "test_and_optimize/testing_unity_cmock"), + ("test_and_optimize/testing_unity_cmock", "test_and_optimize/test_framework/testing_unity_cmock"), ("ug_tfm", "security/tfm"), ("app_dev/tfm/index", "security/tfm"), ("app_build_system", "config_and_build/config_and_build_system"), @@ -95,12 +100,14 @@ ("installation/installing", "installation/install_ncs"), ("gs_modifying", "config_and_build/modifying"), ("getting_started/modifying", "config_and_build/modifying"), + ("config_and_build/modifying", "config_and_build/configuring_app/index"), ("gs_programming", "config_and_build/programming"), ("getting_started/programming", "config_and_build/programming"), ("gs_recommended_versions", "installation/recommended_versions"), ("getting_started/recommended_versions", "installation/recommended_versions"), ("gs_testing", "test_and_optimize/testing"), ("getting_started/testing", "test_and_optimize/testing"), + ("test_and_optimize/testing", "test_and_optimize"), ("gs_updating", "installation/updating"), ("getting_started/updating", "installation/updating"), ("ug_nrf52", "device_guides/nrf52"), @@ -200,6 +207,7 @@ ("samples/samples_thread","samples/thread"), ("samples/samples_wifi","samples/wifi"), ("samples/samples_zigbee","samples/zigbee"), + ("samples/wifi/sr_coex/README","samples/wifi/ble_coex/README"), ("security_chapter","security/security"), ("security","security/security"), ("ug_nrf52_developing","device_guides/working_with_nrf/nrf52/developing"), @@ -220,10 +228,20 @@ ("working_with_nrf/nrf70/developing/index","device_guides/working_with_nrf/nrf70/developing/index"), ("ug_nrf70_developing_powersave","device_guides/working_with_nrf/nrf70/developing/powersave"), ("working_with_nrf/nrf70/developing/powersave","device_guides/working_with_nrf/nrf70/developing/powersave"), + ("device_guides/working_with_nrf/nrf70/developing/powersave","protocols/wifi/powersave"), + ("protocols/wifi/powersave","protocols/wifi/station_mode/powersave"), ("ug_nrf70_features","device_guides/working_with_nrf/nrf70/features"), ("working_with_nrf/nrf70/features","device_guides/working_with_nrf/nrf70/features"), ("ug_nrf7002_gs","device_guides/working_with_nrf/nrf70/gs"), ("working_with_nrf/nrf70/gs","device_guides/working_with_nrf/nrf70/gs"), + ("device_guides/working_with_nrf/nrf70/developing/debugging","protocols/wifi/debugging"), + ("device_guides/working_with_nrf/nrf70/developing/raw_tx_operation","protocols/wifi/raw_tx_operation"), + ("protocols/wifi/raw_tx_operation","protocols/wifi/advanced_modes/raw_tx_operation"), + ("device_guides/working_with_nrf/nrf70/developing/regulatory_support","protocols/wifi/regulatory_support"), + ("device_guides/working_with_nrf/nrf70/developing/sap","protocols/wifi/sap"), + ("device_guides/working_with_nrf/nrf70/developing/scan_operation","protocols/wifi/scan_operation"), + ("protocols/wifi/scan_operation","protocols/wifi/scan_mode/scan_operation"), + ("protocols/wifi/sniffer_rx_operation","protocols/wifi/advanced_modes/sniffer_rx_operation"), ("ug_nrf9160","device_guides/working_with_nrf/nrf91/nrf9160"), ("working_with_nrf/nrf91/nrf9160","device_guides/working_with_nrf/nrf91/nrf9160"), ("ug_nrf9160_gs","device_guides/working_with_nrf/nrf91/nrf9160_gs"), @@ -236,4 +254,24 @@ ("working_with_nrf/nrf91/thingy91_gsg","device_guides/working_with_nrf/nrf91/thingy91_gsg"), ("known_issues","releases_and_maturity/known_issues"), ("libraries/networking/nrf_cloud_agps","libraries/networking/nrf_cloud_agnss"), + ("applications/nrf5340_audio/README","applications/nrf5340_audio/index"), + ("libraries/nrf_security/index", "libraries/security/nrf_security/index"), + ("libraries/nrf_security/doc/backend_config", "libraries/security/nrf_security/doc/backend_config"), + ("libraries/nrf_security/doc/configuration", "libraries/security/nrf_security/doc/configuration"), + ("libraries/nrf_security/doc/driver_config", "libraries/security/nrf_security/doc/driver_config"), + ("libraries/nrf_security/doc/drivers", "libraries/security/nrf_security/doc/drivers"), + ("libraries/nrf_security/doc/mbed_tls_header", "libraries/security/nrf_security/doc/mbed_tls_header"), + ("libraries/bin/bt_ll_acs_nrf53/index", "nrfxlib/softdevice_controller/doc/isochronous_channels"), + ("libraries/others/fatal_error", "libraries/security/fatal_error"), + ("libraries/others/flash_patch", "libraries/security/bootloader/flash_patch"), + ("libraries/others/fprotect", "libraries/security/bootloader/fprotect"), + ("libraries/others/fw_info", "libraries/security/bootloader/fw_info"), + ("libraries/others/hw_unique_key", "libraries/security/hw_unique_key"), + ("libraries/others/identity_key", "libraries/security/identity_key"), + ("libraries/tfm/index", "libraries/security/tfm/index"), + ("libraries/tfm/tfm_ioctl_api", "libraries/security/tfm/tfm_ioctl_api"), + ("libraries/bootloader/bl_crypto", "libraries/security/bootloader/bl_crypto"), + ("libraries/bootloader/bl_storage", "libraries/security/bootloader/bl_storage"), + ("libraries/bootloader/bl_validation", "libraries/security/bootloader/bl_validation"), + ("libraries/bootloader/index", "libraries/security/bootloader/index"), ] diff --git a/doc/kconfig/conf.py b/doc/kconfig/conf.py index 89646115639..cf03f8c4ddd 100644 --- a/doc/kconfig/conf.py +++ b/doc/kconfig/conf.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Nordic Semiconductor +# Copyright (c) 2024 Nordic Semiconductor # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # @@ -23,7 +23,7 @@ # General configuration -------------------------------------------------------- project = "Kconfig reference" -copyright = "2019-2023, Nordic Semiconductor" +copyright = "2019-2024, Nordic Semiconductor" author = "Nordic Semiconductor" # NOTE: use blank space as version to preserve space version = " " diff --git a/doc/matter/conf.py b/doc/matter/conf.py index 248f51cc433..8941d9a131b 100644 --- a/doc/matter/conf.py +++ b/doc/matter/conf.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Nordic Semiconductor +# Copyright (c) 2024 Nordic Semiconductor # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # @@ -21,9 +21,9 @@ # General configuration -------------------------------------------------------- project = "Matter SDK" -copyright = "2020-2023, Matter Contributors" +copyright = "2020-2024, Matter Contributors" author = "Matter Contributors" -version = "1.1.0" +version = "1.2.0" sys.path.insert(0, str(ZEPHYR_BASE / "doc" / "_extensions")) sys.path.insert(0, str(NRF_BASE / "doc" / "_extensions")) @@ -59,11 +59,14 @@ (MATTER_BASE / "docs" / "guides", "nrfconnect_examples_configuration.md"), (MATTER_BASE / "docs" / "guides", "nrfconnect_examples_cli.md"), (MATTER_BASE / "docs" / "guides", "nrfconnect_examples_software_update.md"), + (MATTER_BASE / "docs" / "guides", "openthread_border_router_pi.md"), + (MATTER_BASE / "docs" / "guides", "openthread_rcp_nrf_dongle.md"), (MATTER_BASE / "docs" / "guides", "nrfconnect_factory_data_configuration.md"), (MATTER_BASE / "docs" / "guides", "BUILDING.md"), (MATTER_BASE / "docs" / "guides", "chip_tool_guide.md"), (MATTER_BASE / "docs" / "guides", "access-control-guide.md"), (MATTER_BASE / "src" / "tools" / "chip-cert", "README.md"), + ] diff --git a/doc/matter/index.rst b/doc/matter/index.rst index 687e35e3204..d9ba49d7b5f 100644 --- a/doc/matter/index.rst +++ b/doc/matter/index.rst @@ -17,6 +17,8 @@ This documentation set includes a selection of pages available in the `Matter `_. + .. toctree:: :maxdepth: 1 :glob: :caption: Subpages: + ../../applications/asset_tracker_v2/README ../../applications/connectivity_bridge/README + ../../applications/ipc_radio/README ../../applications/matter_bridge/README - ../../applications/asset_tracker_v2/README - ../../applications/serial_lte_modem/README + ../../applications/nrf5340_audio/index ../../applications/nrf_desktop/README - ../../applications/nrf5340_audio/doc/index ../../applications/machine_learning/README + ../../applications/serial_lte_modem/README ../../applications/matter_weather_station/README ../../applications/zigbee_weather_station/README diff --git a/doc/nrf/conf.py b/doc/nrf/conf.py index f3aaee7d886..0e6b55d43df 100644 --- a/doc/nrf/conf.py +++ b/doc/nrf/conf.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Nordic Semiconductor +# Copyright (c) 2024 Nordic Semiconductor # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # @@ -26,9 +26,9 @@ # General configuration -------------------------------------------------------- project = "nRF Connect SDK" -copyright = "2019-2023, Nordic Semiconductor" +copyright = "2019-2024, Nordic Semiconductor" author = "Nordic Semiconductor" -version = release = "2.5.99" +version = release = "2.6.99" sys.path.insert(0, str(ZEPHYR_BASE / "doc" / "_extensions")) sys.path.insert(0, str(NRF_BASE / "doc" / "_extensions")) diff --git a/doc/nrf/config_and_build.rst b/doc/nrf/config_and_build.rst index ef2fa71eaf9..7b02a1248ed 100644 --- a/doc/nrf/config_and_build.rst +++ b/doc/nrf/config_and_build.rst @@ -4,9 +4,11 @@ Configuration and building ########################## -The |NCS| build and configuration system is based on the one from :ref:`Zephyr project `, with some additions. +After you have :ref:`created an application `, you need to configure and build it in order to be able to run it. -The figure below visualizes the tools and configuration methods in the |NCS|. +The |NCS| configuration and build system is based on the one from :ref:`Zephyr `, with some additions. + +The following figure lists the main tools and configuration methods in the |NCS|. All of them have a role in the creation of an application, from configuring the libraries or applications to building them. .. figure:: images/ncs-toolchain.svg @@ -14,29 +16,30 @@ All of them have a role in the creation of an application, from configuring the |NCS| tools and configuration methods -* CMake generates build files based on the provided :file:`CMakeLists.txt` files, which use information from Kconfig and devicetree. - See the `CMake documentation`_. -* :ref:`Devicetree ` describes the hardware. -* :ref:`zephyr:kconfig` generates definitions that configure the software. -* Ninja (comparable to Make) uses the build files to build the program, see the `Ninja documentation`_. -* The compiler (for example, `GCC compiler`_) creates the executables. +* Devicetree describes the hardware. +* Kconfig generates definitions that configure the software. +* Partition Manager describes the memory layout. +* CMake generates build files based on the provided :file:`CMakeLists.txt` files, which use information from devicetree files, Kconfig, and Partition Manager. +* Ninja (comparable to Make) uses the build files to build the program. +* The compiler (for example, GCC) creates the executables. + +For a more detailed overview, see :ref:`app_build_system`. -Read the guides in this section to learn how to use these tools and configuration methods in areas valid for :ref:`all supported boards `. Depending on the board you are working with, check also its :ref:`hardware guide `, as some nRF Series families have specific exceptions and rules to be applied on top of the general configuration procedures. Make sure to consider :ref:`app_bootloaders` and :ref:`app_dfu` already at this stage of the application development. +.. note:: + If you want to go through dedicated training related to some of the topics covered here, enroll in the `nRF Connect SDK Intermediate course`_ in the `Nordic Developer Academy`_. + .. toctree:: :maxdepth: 1 :caption: Subpages: config_and_build/config_and_build_system - config_and_build/board_support - config_and_build/pin_control - config_and_build/use_gpio_pin_directly + config_and_build/board_support/index + config_and_build/configuring_app/index config_and_build/programming - config_and_build/output_build_files - config_and_build/modifying config_and_build/multi_image config_and_build/bootloaders/index config_and_build/dfu/index diff --git a/doc/nrf/config_and_build/board_support.rst b/doc/nrf/config_and_build/board_support.rst deleted file mode 100644 index 86412db49e3..00000000000 --- a/doc/nrf/config_and_build/board_support.rst +++ /dev/null @@ -1,210 +0,0 @@ -.. _app_boards: - -Board support -############# - -.. contents:: - :local: - :depth: 2 - -The |NCS| provides board definitions for all Nordic Semiconductor devices. -In addition, you can define custom boards. - -.. _app_boards_names: -.. _programming_board_names: - -Board names -*********** - -The following tables list all boards and build targets for Nordic Semiconductor's hardware platforms. - -The build target column uses several entries for multi-core hardware platforms: - -* For core type: - - * ``cpuapp`` - When you choose this target, you build the application core firmware. - * ``cpunet`` - When you choose this target, you build the network core firmware. - -* For usage of Cortex-M Security Extensions (CMSE): - - * Entries without ``*_ns`` (``cpuapp``) - When you choose this target, you build the application core firmware as a single execution environment that does not use CMSE (:ref:`Trusted Firmware-M (TF-M) `). - * Entries with ``*_ns`` (for example, ``cpuapp_ns``) - When you choose this target, you build the application with CMSE. - The application core firmware is placed in Non-Secure Processing Environment (NSPE) and uses Secure Processing Environment (SPE) for security features. - By default, the build system automatically includes :ref:`Trusted Firmware-M (TF-M) ` in SPE and merges it with NSPE. - -Read more about separation of processing environments in the :ref:`app_boards_spe_nspe` section. - -.. _app_boards_names_zephyr: - -Boards included in sdk-zephyr -============================= - -The following boards are defined in the :file:`zephyr/boards/arm/` folder. -Also see the :ref:`zephyr:boards` section in the Zephyr documentation. - -.. _table: - -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| Hardware platform | PCA number | Board name | Build target | -+===================+============+===================================================================+=======================================+ -| nRF52 DK | PCA10040 | :ref:`nrf52dk_nrf52832 ` | ``nrf52dk_nrf52832`` | -| (nRF52832) | +-------------------------------------------------------------------+---------------------------------------+ -| | | :ref:`nrf52dk_nrf52810 ` | ``nrf52dk_nrf52810`` | -| | +-------------------------------------------------------------------+---------------------------------------+ -| | | :ref:`nrf52dk_nrf52805 ` | ``nrf52dk_nrf52805`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF52833 DK | PCA10100 | :ref:`nrf52833dk_nrf52833 ` | ``nrf52833dk_nrf52833`` | -| | +-------------------------------------------------------------------+---------------------------------------+ -| | | :ref:`nrf52833dk_nrf52820 ` | ``nrf52833dk_nrf52820`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF52840 DK | PCA10056 | :ref:`nrf52840dk_nrf52840 ` | ``nrf52840dk_nrf52840`` | -| | +-------------------------------------------------------------------+---------------------------------------+ -| | | :ref:`nrf52840dk_nrf52811 ` | ``nrf52840dk_nrf52811`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF52840 Dongle | PCA10059 | :ref:`nrf52840dongle_nrf52840 ` | ``nrf52840dongle_nrf52840`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| Thingy:52 | PCA20020 | :ref:`thingy52_nrf52832 ` | ``thingy52_nrf52832`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF21540 DK | PCA10112 | :ref:`nrf21540dk_nrf52840 ` | ``nrf21540dk_nrf52840`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF5340 DK | PCA10095 | :ref:`nrf5340dk_nrf5340 ` | ``nrf5340dk_nrf5340_cpunet`` | -| | | | | -| | | | ``nrf5340dk_nrf5340_cpuapp`` | -| | | | | -| | | | ``nrf5340dk_nrf5340_cpuapp_ns`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| Thingy:53 | PCA20053 | :ref:`thingy53_nrf5340 ` | ``thingy53_nrf5340_cpunet`` | -| | | | | -| | | | ``thingy53_nrf5340_cpuapp`` | -| | | | | -| | | | ``thingy53_nrf5340_cpuapp_ns`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF5340 Audio | PCA10121 | :ref:`nrf5340_audio_dk_nrf5340 ` | ``nrf5340_audio_dk_nrf5340_cpuapp`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF9160 DK | PCA10090 | :ref:`nrf9160dk_nrf9160 ` | ``nrf9160dk_nrf9160`` | -| | | | | -| | | | ``nrf9160dk_nrf9160_ns`` | -| | +-------------------------------------------------------------------+---------------------------------------+ -| | | :ref:`nrf9160dk_nrf52840 ` | ``nrf9160dk_nrf52840`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ -| nRF9161 DK | PCA10153 | :ref:`nrf9161dk_nrf9161 ` | ``nrf9161dk_nrf9161`` | -| | | | | -| | | | ``nrf9161dk_nrf9161_ns`` | -+-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ - -.. note:: - In |NCS| releases before v1.6.1: - - * The build target ``nrf9160dk_nrf9160_ns`` was named ``nrf9160dk_nrf9160ns``. - * The build target ``nrf5340dk_nrf5340_cpuapp_ns`` was named ``nrf5340dk_nrf5340_cpuappns``. - -.. _app_boards_names_nrf: - -Boards included in sdk-nrf -========================== - -The following boards are defined in the :file:`nrf/boards/arm/` folder. - -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| Hardware platform | PCA number | Board name | Build target | -+===================+============+==========================================================+=======================================+ -| nRF Desktop | PCA20041 | :ref:`nrf52840gmouse_nrf52840 ` | ``nrf52840gmouse_nrf52840`` | -| Gaming Mouse | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF Desktop | PCA20044 | :ref:`nrf52dmouse_nrf52832 ` | ``nrf52dmouse_nrf52832`` | -| Mouse | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF Desktop | PCA20045 | :ref:`nrf52810dmouse_nrf52810 ` | ``nrf52810dmouse_nrf52810`` | -| Mouse | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF Desktop | PCA20037 | :ref:`nrf52kbd_nrf52832 ` | ``nrf52kbd_nrf52832`` | -| Keyboard | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF Desktop | PCA10111 | :ref:`nrf52833dongle_nrf52833 ` | ``nrf52833dongle_nrf52833`` | -| Dongle | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF Desktop | PCA10114 | :ref:`nrf52820dongle_nrf52820 ` | ``nrf52820dongle_nrf52820`` | -| Dongle | | | | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| Thingy:91 | PCA20035 | :ref:`thingy91_nrf9160 ` | ``thingy91_nrf9160`` | -| | | | | -| | | | ``thingy91_nrf9160_ns`` | -| | +----------------------------------------------------------+---------------------------------------+ -| | | :ref:`thingy91_nrf52840 ` | ``thingy91_nrf52840`` | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ -| nRF7002 DK | PCA10143 | :ref:`nrf7002dk_nrf5340 ` | ``nrf7002dk_nrf5340_cpunet`` | -| | | | | -| | | | ``nrf7002dk_nrf5340_cpuapp`` | -| | | | | -| | | | ``nrf7002dk_nrf5340_cpuapp_ns`` | -+-------------------+------------+----------------------------------------------------------+---------------------------------------+ - -The :ref:`nRF21540 EK shield ` is defined in the :file:`nrf/boards/shields` folder. - -Custom boards -************* - -Defining your own board is a very common step in application development, because applications are typically designed to run on boards that are not directly supported by the |NCS|, and are often custom designs not available publicly. -To define your own board, you can use the following Zephyr guides as reference, since boards are defined in the |NCS| just as they are in Zephyr: - -* :ref:`custom_board_definition` is a guide to adding your own custom board to the Zephyr build system. -* :ref:`board_porting_guide` is a complete guide to porting Zephyr to your own board. - -One of the |NCS| applications that lets you add custom boards is :ref:`nrf_desktop`. -See :ref:`nrf_desktop_porting_guide` in the application documentation for details. - -.. _app_boards_spe_nspe: - -Processing environments -*********************** - -The build target column in the tables above separates entries according to the CPU to target (for multi-core SoCs) and whether Cortex-M Security Extensions (CMSE) are used or not (addition of ``_ns`` if they are used). - -When CMSE is used, the firmware is split in accordance with the security by separation architecture principle to better protect sensitive assets and code. -With CMSE, the firmware is stored in one of two security environments (flash partitions), either Secure Processing Environment (SPE) or Non-Secure Processing Environment (NSPE). -This isolation of firmware is only possible if the underlying hardware supports `ARM TrustZone`_. - -.. figure:: images/spe_nspe.svg - :alt: Processing environments in the |NCS| - - Processing environments in the |NCS| - -In Zephyr and the |NCS|, SPE and NSPE are used exclusively in the context of the application core of a multi-core SoC. -Building follows the security by separation principle and depends on the build target. - -.. _app_boards_spe_nspe_cpuapp: - -Building for ``cpuapp`` (CMSE disabled) -======================================= - -When you build for ``cpuapp``, you build the firmware for the application core without CMSE. -Because CMSE is disabled, TF-M is not used and there is no separation of firmware. - -.. _app_boards_spe_nspe_cpuapp_ns: - -Building for ``*_ns`` (CMSE enabled) -==================================== - -When you build for ``*_ns``, you build firmware with CMSE. -Firmware is separated in the following way: - -* SPE implements security-critical functionality and data (including bootloaders) and isolates them from the application software in NSPE. - It also contains secure firmware running in the secure state. -* NSPE typically implements the user application and communication firmware, among other major components. - -The application is built as a non-secure image and :ref:`Trusted Firmware-M (TF-M) ` is built as the secure image. -The build system merges both images to form a combined image that will be used for programming or updating the device. - -TF-M enables hardware-supported separation of firmware. -It also implements `Platform Security Architecture (PSA)`_ API, which provides security features for the system, including roots of trust for protecting secrets, platform state, and cryptographic keys. -The API coordinates the communication with the components in NSPE. - -More information about SPE and NSPE ------------------------------------ - -Read the following pages for a better understanding of security by separation in the |NCS|: - -* :ref:`ug_tfm` -* :ref:`debugging_spe_nspe` -* `An Introduction to Trusted Firmware-M (TF-M)`_ on DevZone -* `TF-M documentation`_ diff --git a/doc/nrf/config_and_build/board_support/board_names.rst b/doc/nrf/config_and_build/board_support/board_names.rst new file mode 100644 index 00000000000..a6a4765515e --- /dev/null +++ b/doc/nrf/config_and_build/board_support/board_names.rst @@ -0,0 +1,171 @@ +.. _app_boards_names: +.. _programming_board_names: + +Board names +########### + +.. contents:: + :local: + :depth: 2 + +The following tables list all boards and build targets for Nordic Semiconductor's hardware platforms. + +The build target column uses several entries for multi-core hardware platforms: + +* For core type: + + * ``cpuapp`` - When you choose this target, you build the application core firmware. + * ``cpunet`` - When you choose this target, you build the network core firmware. + +* For usage of Cortex-M Security Extensions (CMSE): + + * Entries without ``*_ns`` (``cpuapp``) - When you choose this target, you build the application core firmware as a single execution environment that does not use CMSE (:ref:`Trusted Firmware-M (TF-M) `). + * Entries with ``*_ns`` (for example, ``cpuapp_ns``) - When you choose this target, you build the application with CMSE. + The application core firmware is placed in Non-Secure Processing Environment (NSPE) and uses Secure Processing Environment (SPE) for security features. + By default, the build system automatically includes :ref:`Trusted Firmware-M (TF-M) ` in SPE and merges it with NSPE. + +Read more about separation of processing environments on the :ref:`app_boards_spe_nspe` page. + +.. _app_boards_names_zephyr: + +Boards included in sdk-zephyr +***************************** + +The following boards are defined in the :file:`zephyr/boards/arm/` folder. +Also see the :ref:`zephyr:boards` section in the Zephyr documentation. + +.. _table: + ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| Hardware platform | PCA number | Board name | Build target | ++===================+============+===================================================================+=======================================+ +| nRF9161 DK | PCA10153 | :ref:`nrf9161dk_nrf9161 ` | ``nrf9161dk_nrf9161`` | +| | | | | +| | | | ``nrf9161dk_nrf9161_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF9160 DK | PCA10090 | :ref:`nrf9160dk_nrf9160 ` | ``nrf9160dk_nrf9160`` | +| | | | | +| | | | ``nrf9160dk_nrf9160_ns`` | +| | +-------------------------------------------------------------------+---------------------------------------+ +| | | :ref:`nrf9160dk_nrf52840 ` | ``nrf9160dk_nrf52840`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF9151 DK | PCA10171 | :ref:`nrf9151dk_nrf9151 ` | ``nrf9151dk_nrf9151`` | +| | | | | +| | | | ``nrf9151dk_nrf9151_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF9131 EK | PCA10165 | :ref:`nrf9131ek_nrf9131 ` | ``nrf9131ek_nrf9131`` | +| | | | | +| | | | ``nrf9131ek_nrf9131_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF54H20 DK | PCA10175 | :ref:`nrf54h20dk_nrf54h20 ` | ``nrf54h20dk_nrf54h20_cpuapp`` | +| | | | | +| | | | ``nrf54h20dk_nrf54h20_cpurad`` | +| | | | | +| | | | ``nrf54h20dk_nrf54h20_cpuppr`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF54L15 PDK | PCA10156 | :ref:`nrf54l15pdk_nrf54l15 ` | ``nrf54l15pdk_nrf54l15_cpuapp`` | +| | | | | +| | | | ``nrf54l15pdk_nrf54l15_cpuapp_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF5340 DK | PCA10095 | :ref:`nrf5340dk_nrf5340 ` | ``nrf5340dk_nrf5340_cpunet`` | +| | | | | +| | | | ``nrf5340dk_nrf5340_cpuapp`` | +| | | | | +| | | | ``nrf5340dk_nrf5340_cpuapp_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF5340 Audio | PCA10121 | :ref:`nrf5340_audio_dk_nrf5340 ` | ``nrf5340_audio_dk_nrf5340_cpuapp`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| Thingy:53 | PCA20053 | :ref:`thingy53_nrf5340 ` | ``thingy53_nrf5340_cpunet`` | +| | | | | +| | | | ``thingy53_nrf5340_cpuapp`` | +| | | | | +| | | | ``thingy53_nrf5340_cpuapp_ns`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF52840 DK | PCA10056 | :ref:`nrf52840dk_nrf52840 ` | ``nrf52840dk_nrf52840`` | +| | +-------------------------------------------------------------------+---------------------------------------+ +| | | :ref:`nrf52840dk_nrf52811 ` | ``nrf52840dk_nrf52811`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF52840 Dongle | PCA10059 | :ref:`nrf52840dongle_nrf52840 ` | ``nrf52840dongle_nrf52840`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF52833 DK | PCA10100 | :ref:`nrf52833dk_nrf52833 ` | ``nrf52833dk_nrf52833`` | +| | +-------------------------------------------------------------------+---------------------------------------+ +| | | :ref:`nrf52833dk_nrf52820 ` | ``nrf52833dk_nrf52820`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF52 DK | PCA10040 | :ref:`nrf52dk_nrf52832 ` | ``nrf52dk_nrf52832`` | +| (nRF52832) | +-------------------------------------------------------------------+---------------------------------------+ +| | | :ref:`nrf52dk_nrf52810 ` | ``nrf52dk_nrf52810`` | +| | +-------------------------------------------------------------------+---------------------------------------+ +| | | :ref:`nrf52dk_nrf52805 ` | ``nrf52dk_nrf52805`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| Thingy:52 | PCA20020 | :ref:`thingy52_nrf52832 ` | ``thingy52_nrf52832`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ +| nRF21540 DK | PCA10112 | :ref:`nrf21540dk_nrf52840 ` | ``nrf21540dk_nrf52840`` | ++-------------------+------------+-------------------------------------------------------------------+---------------------------------------+ + +.. note:: + In |NCS| releases before v1.6.1: + + * The build target ``nrf9160dk_nrf9160_ns`` was named ``nrf9160dk_nrf9160ns``. + * The build target ``nrf5340dk_nrf5340_cpuapp_ns`` was named ``nrf5340dk_nrf5340_cpuappns``. + +.. _app_boards_names_nrf: + +Boards included in sdk-nrf +************************** + +The following boards are defined in the :file:`nrf/boards/arm/` folder. + ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| Hardware platform | PCA number | Board name | Build target | ++===================+============+==========================================================+=======================================+ +| nRF Desktop | PCA20041 | :ref:`nrf52840gmouse_nrf52840 ` | ``nrf52840gmouse_nrf52840`` | +| Gaming Mouse | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF Desktop | PCA20044 | :ref:`nrf52dmouse_nrf52832 ` | ``nrf52dmouse_nrf52832`` | +| Mouse | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF Desktop | PCA20045 | :ref:`nrf52810dmouse_nrf52810 ` | ``nrf52810dmouse_nrf52810`` | +| Mouse | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF Desktop | PCA20037 | :ref:`nrf52kbd_nrf52832 ` | ``nrf52kbd_nrf52832`` | +| Keyboard | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF Desktop | PCA10111 | :ref:`nrf52833dongle_nrf52833 ` | ``nrf52833dongle_nrf52833`` | +| Dongle | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF Desktop | PCA10114 | :ref:`nrf52820dongle_nrf52820 ` | ``nrf52820dongle_nrf52820`` | +| Dongle | | | | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| Thingy:91 | PCA20035 | :ref:`thingy91_nrf9160 ` | ``thingy91_nrf9160`` | +| | | | | +| | | | ``thingy91_nrf9160_ns`` | +| | +----------------------------------------------------------+---------------------------------------+ +| | | :ref:`thingy91_nrf52840 ` | ``thingy91_nrf52840`` | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ +| nRF7002 DK | PCA10143 | :ref:`nrf7002dk_nrf5340 ` | ``nrf7002dk_nrf5340_cpunet`` | +| | | | | +| | | | ``nrf7002dk_nrf5340_cpuapp`` | +| | | | | +| | | | ``nrf7002dk_nrf5340_cpuapp_ns`` | ++-------------------+------------+----------------------------------------------------------+---------------------------------------+ + +.. _shield_names_nrf: + +Shields included in sdk-nrf +*************************** + +The following shields are defined in the :file:`nrf/boards/shields` folder. + ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ +| Hardware platform | PCA number | Board name | Build target | ++==========================================================+============+==========================================================================+=======================================+ +| nRF7002 :term:`Evaluation Kit (EK)` | PCA63556 | :ref:`nrf7002ek ` | ``nrf7002ek`` | ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ +| nRF7002 EK with emulated support for the nRF7001 IC | PCA63556 | :ref:`nrf7002ek_nrf7001 ` | ``nrf7002ek_nrf7001`` | ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ +| nRF7002 EK with emulated support for the nRF7000 IC | PCA63556 | :ref:`nrf7002ek_nrf7000 ` | ``nrf7002ek_nrf7000`` | ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ +| nRF7002 :term:`Expansion Board (EB)` | PCA63561 | :ref:`nrf7002eb ` | ``nrf7002eb`` | ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ +| nRF21540 EK | PCA63550 | :ref:`nrf21540ek ` | ``nrf21540ek`` | ++----------------------------------------------------------+------------+--------------------------------------------------------------------------+---------------------------------------+ diff --git a/doc/nrf/config_and_build/board_support/defining_custom_board.rst b/doc/nrf/config_and_build/board_support/defining_custom_board.rst new file mode 100644 index 00000000000..b0d1a107888 --- /dev/null +++ b/doc/nrf/config_and_build/board_support/defining_custom_board.rst @@ -0,0 +1,29 @@ +.. _defining_custom_board: + +Defining custom board +##################### + +Defining your own board is a very common step in application development, because applications are typically designed to run on boards that are not directly supported by the |NCS|, and are often custom designs not available publicly. + +Guidelines for custom boards +**************************** + +To define your own board, you can use the following Zephyr guides as reference, since boards are defined in the |NCS| just as they are in Zephyr: + +* :ref:`custom_board_definition` is a guide to adding your own custom board to the Zephyr build system. +* :ref:`board_porting_guide` is a complete guide to porting Zephyr to your own board. + +Adding a custom board in the |nRFVSC| +************************************* + +The |nRFVSC| lets you add your own boards to your |NCS| project. +Read the `How to work with boards and devices`_ page in the extension documentation for detailed steps. + +Application porting guides +************************** + +Some :ref:`applications` in the |NCS| provide detailed guides for adapting the application to custom boards: + +* :ref:`nrf_desktop` - See :ref:`nrf_desktop_porting_guide` in the application documentation. +* :ref:`nrf53_audio_app` - See :ref:`nrf53_audio_app_adapting` in the application documentation. +* :ref:`nrf_machine_learning_app` - See :ref:`nrf_machine_learning_app_porting_guide` in the application documentation. diff --git a/doc/nrf/config_and_build/images/spe_nspe.svg b/doc/nrf/config_and_build/board_support/images/spe_nspe.svg similarity index 100% rename from doc/nrf/config_and_build/images/spe_nspe.svg rename to doc/nrf/config_and_build/board_support/images/spe_nspe.svg diff --git a/doc/nrf/config_and_build/board_support/index.rst b/doc/nrf/config_and_build/board_support/index.rst new file mode 100644 index 00000000000..03000fed7e8 --- /dev/null +++ b/doc/nrf/config_and_build/board_support/index.rst @@ -0,0 +1,19 @@ +.. _app_boards: + +Board support +############# + +The |NCS| provides board definitions for all Nordic Semiconductor devices. +These are in tables on the :ref:`app_boards_names` page, listed by :ref:`app_boards_names_zephyr`, :ref:`app_boards_names_nrf`, and :ref:`shield_names_nrf`. + +Some boards can support Cortex-M Security Extensions (CMSE), which results in separation of :ref:`app_boards_spe_nspe`. + +In addition, you can :ref:`define custom boards `. + +.. toctree:: + :maxdepth: 1 + :caption: Subpages: + + board_names + processing_environments + defining_custom_board diff --git a/doc/nrf/config_and_build/board_support/processing_environments.rst b/doc/nrf/config_and_build/board_support/processing_environments.rst new file mode 100644 index 00000000000..2b76d9d0848 --- /dev/null +++ b/doc/nrf/config_and_build/board_support/processing_environments.rst @@ -0,0 +1,59 @@ +.. _app_boards_spe_nspe: + +Processing environments +####################### + +.. contents:: + :local: + :depth: 2 + +The :ref:`boards supported by the SDK ` distinguish entries according to the CPU to target (for multi-core SoCs) and whether Cortex-M Security Extensions (CMSE) are used or not (addition of ``_ns`` if they are used). + +When CMSE is used, the firmware is split in accordance with the security by separation architecture principle to better protect sensitive assets and code. +With CMSE, the firmware is stored in one of two security environments (flash partitions), either Secure Processing Environment (SPE) or Non-Secure Processing Environment (NSPE). +This isolation of firmware is only possible if the underlying hardware supports `ARM TrustZone`_. + +.. figure:: images/spe_nspe.svg + :alt: Processing environments in the |NCS| + + Processing environments in the |NCS| + +In Zephyr and the |NCS|, SPE and NSPE are used exclusively in the context of the application core of a multi-core SoC. +Building follows the security by separation principle and depends on the build target. + +.. _app_boards_spe_nspe_cpuapp: + +Building for ``cpuapp`` (CMSE disabled) +*************************************** + +When you build for ``cpuapp``, you build the firmware for the application core without CMSE. +Because CMSE is disabled, TF-M is not used and there is no separation of firmware. + +.. _app_boards_spe_nspe_cpuapp_ns: + +Building for ``*_ns`` (CMSE enabled) +************************************ + +When you build for ``*_ns``, you build firmware with CMSE. +Firmware is separated in the following way: + +* SPE implements security-critical functionality and data (including bootloaders) and isolates them from the application software in NSPE. + It also contains secure firmware running in the secure state. +* NSPE typically implements the user application and communication firmware, among other major components. + +The application is built as a non-secure image and :ref:`Trusted Firmware-M (TF-M) ` is built as the secure image. +The build system merges both images to form a combined image that will be used for programming or updating the device. + +TF-M enables hardware-supported separation of firmware. +It also implements `Platform Security Architecture (PSA)`_ API, which provides security features for the system, including roots of trust for protecting secrets, platform state, and cryptographic keys. +The API coordinates the communication with the components in NSPE. + +More information about SPE and NSPE +=================================== + +Read the following pages for a better understanding of security by separation in the |NCS|: + +* :ref:`ug_tfm` +* :ref:`debugging_spe_nspe` +* `An Introduction to Trusted Firmware-M (TF-M)`_ on DevZone +* `TF-M documentation`_ diff --git a/doc/nrf/config_and_build/bootloaders/bootloader_adding.rst b/doc/nrf/config_and_build/bootloaders/bootloader_adding.rst index 51c470bb71e..68d1dd9063b 100644 --- a/doc/nrf/config_and_build/bootloaders/bootloader_adding.rst +++ b/doc/nrf/config_and_build/bootloaders/bootloader_adding.rst @@ -143,11 +143,10 @@ See :ref:`ug_fw_update_keys` for information on how to generate custom keys for Additionally, the |NSIB| supports the following methods for signing images with private keys: -* :ref:`ug_fw_update_keys_python` - The default method, using the :kconfig:option:`CONFIG_SB_SIGNING_PYTHON`. -* :ref:`ug_fw_update_keys_openssl` - Uses the :kconfig:option:`CONFIG_SB_SIGNING_OPENSSL`. -* :ref:`Using a custom command ` - Uses the :kconfig:option:`CONFIG_SB_SIGNING_CUSTOM`. +* :ref:`ug_fw_update_keys_openssl` - Uses the :kconfig:option:`CONFIG_SB_SIGNING_OPENSSL` Kconfig option. +* :ref:`Using a custom command ` - Uses the :kconfig:option:`CONFIG_SB_SIGNING_CUSTOM` Kconfig option. -Both Python and OpenSSL methods are handled internally by the build system, whereas using custom commands requires more configuration steps. +The OpenSSL method is handled internally by the build system, whereas using custom commands requires more configuration steps. Checking the public key ^^^^^^^^^^^^^^^^^^^^^^^ @@ -319,7 +318,7 @@ To use MCUboot as an upgradable bootloader to your application, complete the fol -DCONFIG_BOOTLOADER_MCUBOOT=y \ -DCONFIG_SECURE_BOOT=y \ -Dmcuboot_CONF_FILE=prj_minimal.conf \ - -Dmcuboot_OVERLAY_CONFIG=external_crypto.conf + -Dmcuboot_EXTRA_CONF_FILE=external_crypto.conf See :ref:`ug_bootloader_config` for more information about using Kconfig fragments with bootloaders. diff --git a/doc/nrf/config_and_build/bootloaders/bootloader_config.rst b/doc/nrf/config_and_build/bootloaders/bootloader_config.rst index 0ff1d48c02d..df29f5660dc 100644 --- a/doc/nrf/config_and_build/bootloaders/bootloader_config.rst +++ b/doc/nrf/config_and_build/bootloaders/bootloader_config.rst @@ -20,7 +20,7 @@ However, there are other ways to customize your application using Kconfig option Using custom project configurations *********************************** -You can use custom project configuration options for the associated image, specifying them at build time using :ref:`ug_multi_image_variables`, either temporarily until you clean the build pristinely or permamently. +You can use custom project configuration options for the associated image, specifying them at build time using :ref:`ug_multi_image_variables`, either temporarily until you clean the build pristinely or permanently. For example, you can temporarily assign custom project configurations for both the bootloaders and a sample application as follows: @@ -51,7 +51,7 @@ For example, you can assign the :file:`my-custom-fragment.conf` fragment to the west build -b nrf52840dk_nrf52840 zephyr/samples/hello_world -- \ -DCONFIG_SECURE_BOOT=y \ -DCONFIG_BOOTLOADER_MCUBOOT=y \ - -Db0_OVERLAY_CONFIG=my-custom-fragment.conf + -Db0_EXTRA_CONF_FILE=my-custom-fragment.conf In the same way, you can replace ``b0`` with ``mcuboot`` to apply the :file:`my-custom-fragment.conf` fragment to the MCUboot image: @@ -60,7 +60,7 @@ In the same way, you can replace ``b0`` with ``mcuboot`` to apply the :file:`my- west build -b nrf52840dk_nrf52840 zephyr/samples/hello_world -- \ -DCONFIG_SECURE_BOOT=y \ -DCONFIG_BOOTLOADER_MCUBOOT=y \ - -Dmcuboot_OVERLAY_CONFIG=my-custom-fragment.conf + -Dmcuboot_EXTRA_CONF_FILE=my-custom-fragment.conf You can use this method to apply Kconfig fragments to any child image in the build, as well as to set any Kconfig option that can be set from the command line. diff --git a/doc/nrf/config_and_build/bootloaders/bootloader_external_flash.rst b/doc/nrf/config_and_build/bootloaders/bootloader_external_flash.rst index 41bd69aadaa..3ced22b1a20 100644 --- a/doc/nrf/config_and_build/bootloaders/bootloader_external_flash.rst +++ b/doc/nrf/config_and_build/bootloaders/bootloader_external_flash.rst @@ -13,14 +13,27 @@ When using MCUboot, you can store the storage partition for the secondary slot i * Single-byte read and write. * Writing data from the internal flash memory to the external flash memory. +To enable external flash with MCUboot, complete the following steps: + +1. Follow the instructions in :ref:`pm_external_flash`, which enables external flash use in the nRF5340 DK's DTS file. + +#. Enable the :kconfig:option:`CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY` Kconfig option. + (Depending on the build configuration, this option will be set to ``y`` automatically.) + +#. Update the ``CONFIG_BOOT_MAX_IMG_SECTORS`` `MCUboot Kconfig option`_ accordingly for child images. + This option defines the maximum number of image sectors MCUboot can handle, as MCUboot typically increases slot sizes when external flash is enabled. + Otherwise the ``CONFIG_BOOT_MAX_IMG_SECTORS`` Kconfig option defaults to the value used for internal flash, and the application may not boot if the value is set too low. + + (The image sector size is the same as the flash erase-block-size across all |NCS| integrated memory.) + .. note:: - The Partition Manager will only support run-time access to flash partitions defined in regions placed on external flash devices that have drivers compiled in. - Partition Manager cannot determine which partitions will be used at runtime, but only those that have drivers enabled, and those are included into the partition map. + The :ref:`partition_manager` will only support run-time access to flash partitions defined in regions placed on external flash devices that have drivers compiled in. + The Partition Manager cannot determine which partitions will be used at runtime, but only those that have drivers enabled, and those are included into the partition map. Lack of partition access will cause MCUboot to fail at runtime. For more details on configuring and enabling access to external flash devices, see :ref:`pm_external_flash`. -The QSPI NOR flash memory driver supports these features, and it can access the QSPI external flash memory of the nRF52840 DK and nRF5340 DK. +The Quad Serial Peripheral Interface (QSPI) NOR flash memory driver supports these features, and it can access the QSPI external flash memory of the nRF52840 DK and nRF5340 DK. See the test in :file:`tests/modules/mcuboot/external_flash` for reference. This test passes both devicetree overlay files and Kconfig fragments to the MCUboot child image through its :file:`child_image` folder. @@ -46,6 +59,10 @@ This error could be caused by the following issues: See :ref:`pm_external_flash` for details. * An out-of-tree external flash driver is not selecting :kconfig:option:`CONFIG_PM_EXTERNAL_FLASH_HAS_DRIVER`, resulting in partitions for images located in the external flash memory being not accessible. + See :ref:`pm_external_flash` for details. + + * Insufficient value set for the ``CONFIG_BOOT_MAX_IMG_SECTORS`` Kconfig option, as MCUboot typically increases slot sizes when external flash is enabled. + See `MCUboot's Kconfig options used in Zephyr `_ for details. The compilation could fail, reporting a linker error similar to following: diff --git a/doc/nrf/config_and_build/bootloaders/bootloader_signature_keys.rst b/doc/nrf/config_and_build/bootloaders/bootloader_signature_keys.rst index 8faf3a2e35e..89459073c22 100644 --- a/doc/nrf/config_and_build/bootloaders/bootloader_signature_keys.rst +++ b/doc/nrf/config_and_build/bootloaders/bootloader_signature_keys.rst @@ -14,7 +14,7 @@ Dedicated host tools like :doc:`mcuboot:imgtool` can be used to sign application When you use |NSIB|, a private/public key pair is by default generated during the build when you are :ref:`ug_bootloader_adding_immutable_keys`. You can use the methods described in the following sections to explicitly define how the key pair is to be generated. -When you use MCUboot or you are :ref:`ug_bootloader_adding_upgradable_mcuboot`, MCUBoot uses keys that were generated once and are stored in the public MCUboot Git repository be default. +When you use MCUboot or you are :ref:`ug_bootloader_adding_upgradable_mcuboot`, MCUboot uses keys that were generated once and are stored in the public MCUboot Git repository by default. .. note:: These key pairs should only be used during development. @@ -27,7 +27,11 @@ The |NCS| supports the following most common ways to generate private/public key * :ref:`ug_fw_update_keys_openssl` * :ref:`ug_fw_update_keys_imgtool` -* :ref:`ug_fw_update_keys_python` + +.. caution:: + + The security of the firmware update process depends on the secrecy of the private key. + You must prevent unauthorized access to the private key. .. _ug_fw_update_keys_openssl: @@ -99,21 +103,6 @@ Examples of imgtool used to create some commonly used key types: For a full list of supported types, use the ``--help`` argument with the tool or any of its commands. -.. _ug_fw_update_keys_python: - -Using Python to generate keys -============================= - -The |NCS| includes an internal script to interact with private and public keys with the |NSIB|. -This script is maintained by the |NCS| team and uses the ``ecdsa`` package available from PyPI. -It is only valid for use with ECDSA keys. - -An example of this internal Python script used to generate keys. - -.. code-block:: console - - python3 nrf/scripts/bootloader/keygen.py --private -o priv.pem - .. _ug_fw_update_development_keys: Using development keys @@ -148,11 +137,7 @@ See :kconfig:option:`CONFIG_SB_PUBLIC_KEY_FILES` for details on how this mechani You can add this feature to your own project and check its functionality as follows: -1. Use the :ref:`bootloader Python script ` to generate two or more private keys for the application and extract a public key for each one: - - .. code-block:: console - - python3 nrf/scripts/bootloader/keygen.py --public -i priv.pem -o pub.pem +1. Generate two or more private keys for the application and extract a public key for each one (for example, using :ref:`OpenSSL `). #. Compile the application and bootloader with the relevant configurations, using only absolute paths: diff --git a/doc/nrf/config_and_build/bootloaders/index.rst b/doc/nrf/config_and_build/bootloaders/index.rst index a6949eab476..74e345495f2 100644 --- a/doc/nrf/config_and_build/bootloaders/index.rst +++ b/doc/nrf/config_and_build/bootloaders/index.rst @@ -33,7 +33,7 @@ You can find an overview of currently supported bootloaders in the table below: - Can be second-stage - Key type support - Public key revocation - - SMP updates + - SMP updates by the application - Downgrade protection - Versioning - Update methods (supported by |NCS|) diff --git a/doc/nrf/config_and_build/config_and_build_system.rst b/doc/nrf/config_and_build/config_and_build_system.rst index 7d5a3334c49..d2d5a025b7e 100644 --- a/doc/nrf/config_and_build/config_and_build_system.rst +++ b/doc/nrf/config_and_build/config_and_build_system.rst @@ -38,7 +38,8 @@ The build and configuration system in Zephyr and the |NCS| uses the following bu - :file:`Kconfig`, :file:`prj.conf`, :file:`.config` - Software configuration system also used in the Linux kernel. - `Kconfig GUI `_, :ref:`menuconfig and guiconfig ` - - Kconfig GUI is part of the |nRFVSC|. + - | Kconfig GUI is part of the |nRFVSC|. + | The :ref:`Kconfig Reference ` provides the documentation for each configuration option. * - :ref:`partition_manager` - :file:`pm.yml`, :file:`pm_static.yml` - Memory layout configuration system. @@ -49,17 +50,22 @@ Each of these systems comes with a specialized syntax and purpose. See the following sections for more information. To read more about Zephyr's configuration system and its role in the application development, see :ref:`zephyr:build_overview` and :ref:`zephyr:application` in the Zephyr documentation. -When you :ref:`create_application`, the configuration files for each of these systems are created in the :ref:`application directory `: :file:`CMakeLists.txt` for CMake, :file:`app.overlay` for Devicetree, :file:`prj.conf` for Kconfig, and :file:`partitions.yml` for Partition Manager (if enabled). -You can then edit them according to your needs (see :ref:`modifying`). +When you :ref:`create_application`, the configuration files for each of these systems are created in the :ref:`application directory `: :file:`CMakeLists.txt` for CMake, :file:`app.overlay` for devicetree, :file:`prj.conf` for Kconfig, and :file:`partitions.yml` for Partition Manager (if enabled). +You can then edit them according to your needs (see :ref:`building`). When you start building, a CMake build is executed in two stages: configuration phase and building phase. +.. figure:: ../images/ncs-toolchain.svg + :alt: nRF Connect SDK tools and configuration + + |NCS| tools and configuration methods + .. _configuration_system_overview_config: Configuration phase =================== -During this phase, CMake executes build scripts from :file:`CMakeLists.txt` and gathers configuration from different sources, for example :ref:`app_build_additions_build_types`, to generate the final build scripts and create a model of the build for the specified build target. +During this phase, CMake executes build scripts from :file:`CMakeLists.txt` and gathers configuration from different sources, for example :ref:`app_build_file_suffixes`, to generate the final build scripts and create a model of the build for the specified build target. The result of this process is a :term:`build configuration`, a set of files that will drive the build process. For more information about this phase, see the respective sections on Zephyr's :ref:`zephyr:cmake-details` page, which describes in-depth the usage of CMake for Zephyr-based applications. @@ -94,7 +100,7 @@ The preprocessed devicetree sources are parsed by the :file:`zephyr/scripts/dts/ The :file:`zephyr.dts` file contains the entire hardware-related configuration of the system in the devicetree format. The header file contains the same kind of information, but with defines usable by source code. -For more information, see :ref:`configure_application` and Zephyr's :ref:`zephyr:dt-guide`. +For more information, see :ref:`configuring_devicetree` and Zephyr's :ref:`zephyr:dt-guide`. In particular, :ref:`zephyr:set-devicetree-overlays` explains how to use devicetree and its overlays to customize an application's devicetree. .. _configure_application_sw: @@ -114,6 +120,7 @@ The :file:`.config` file in the :file:`/zephyr/` directory describes Some subsystems can use their own configuration files. For more information, see :ref:`configure_application` and Zephyr's :ref:`zephyr:application-kconfig`. +The :ref:`Kconfig Reference ` provides the documentation for each configuration option in the |NCS|. Memory layout configuration --------------------------- @@ -143,14 +150,43 @@ Each child image is a separate application. For more information, see :ref:`ug_multi_image`. +.. _app_build_file_suffixes: + +Custom configurations +--------------------- + +Zephyr provides the :ref:`zephyr:application-file-suffixes` feature for applications that require a single code base with multiple configurations for different product or build variants (or both). +When you select a given file suffix for the :ref:`configuration phase `, the build system will use a specific set of files to create a specific build configuration for the application. +If it does not find files that match the provided suffix, the build system will fall back to the default files without suffix. + +The file suffix can be any string, but many applications and samples in the |NCS| use ``release``. +This suffix can be included in the :file:`prj.conf` file name (for example, :file:`prj_release.conf`), and also in file names for board configurations, child image Kconfig configurations, and others. +In this way, these files are made dependent on the given configuration and are only used when that build configuration is generated. +For example, if an application uses a custom :file:`nrf5340dk_nrf5340_cpuapp_release.overlay` overlay file, this file will be used together with the application's :file:`prj_release.conf` when you set :makevar:`FILE_SUFFIX` to ``release`` (``-DFILE_SUFFIX=release``). + +Many applications and samples in the |NCS| define even more detailed build configurations. +For example, the :ref:`Zigbee light switch ` sample features the ``fota`` configuration. +See the Configuration section of the given application or sample's documentation for information on if it includes any custom configurations. + +.. important:: + The file suffixes feature is replacing the :ref:`app_build_additions_build_types` that used the :makevar:`CONF_FILE` variable. + File suffixes are backward compatible with this variable, but the following software components are not compatible with file suffixes: + + * :ref:`Child image Kconfig configuration `. + Use the :makevar:`CONF_FILE` variable during the deprecation period of the build types. + * |file_suffix_partition_manager_exception| + +For information about how to provide file suffixes when building an application, see :ref:`cmake_options`. + .. _configuration_system_overview_build: Building phase ============== During this phase, the final build scripts are executed. -The build phase begins when the user invokes ``make`` or ``ninja``. -You can customize this stage by :ref:`cmake_options`. +The build phase begins when the user invokes ``make`` or `ninja `_. +The compiler (for example, `GCC compiler`_) then creates object files used to create the final executables. +You can customize this stage by :ref:`cmake_options` and using :ref:`compiler_settings`. The result of this process is a complete application in a format suitable for flashing on the desired target board. See :ref:`output build files ` for details. @@ -185,10 +221,18 @@ For example, when building a sample that enables :kconfig:option:`CONFIG_BT_EXT_ To disable these warnings, disable the :kconfig:option:`CONFIG_WARN_EXPERIMENTAL` Kconfig option. .. _app_build_additions_build_types: +.. _gs_modifying_build_types: +.. _modifying_build_types: Custom build types ================== +.. important:: + The build types are deprecated and are being replaced by :ref:`suffix-based configurations ` and Zephyr's :ref:`zephyr:sysbuild`. + You can continue to use the build types feature until the transition is complete in the |NCS|. + It is still required for applications that use build types with :ref:`multiple images ` or Partition Manager's :ref:`static configuration ` (or both). + Check the application and sample documentation pages for which variable to use. + A build type is a feature that defines the way in which the configuration files are to be handled. For example, selecting a build type lets you generate different build configurations for *release* and *debug* versions of the application. @@ -205,7 +249,16 @@ The most common build types are ``release`` and ``debug``, which correspond to C For example, nRF Desktop features a ``wwcb`` build type, while Matter weather station features the ``factory_data`` build type. See the application's Configuration section for information if it includes any build types. -For more information about how to invoke and create build types, see :ref:`modifying_build_types`. +The following software components can be made dependent on the build type: + +* The Partition Manager's :ref:`static configuration `. + When the build type has been inferred, the file :file:`pm_static_.yml` will have precedence over :file:`pm_static.yml`. +* The :ref:`child image Kconfig configuration `. + Certain child image configuration files located in the :file:`child_image/` directory can be defined per build type. + +The devicetree configuration is not affected by the build type. + +For more information about how to invoke build types, see :ref:`cmake_options`. .. _app_build_additions_multi_image: @@ -215,7 +268,7 @@ Multi-image builds The |NCS| build system extends Zephyr's with support for multi-image builds. You can find out more about these in the :ref:`ug_multi_image` section. -The |NCS| allows you to :ref:`create custom build type files ` instead of using a single :file:`prj.conf` file. +The |NCS| allows you to :ref:`build types ` instead of using a single :file:`prj.conf` file. Boilerplate CMake file ====================== @@ -226,13 +279,16 @@ The |NCS| provides an additional :file:`boilerplate.cmake` file that is automati find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) -This file checks if the selected board is supported and, when available, if the selected :ref:`build type ` is supported. +This file checks if the selected board is supported and, when available, if the selected :ref:`file suffix ` or :ref:`build type ` is supported. Partition Manager ================= The |NCS| adds the :ref:`partition_manager` script, responsible for partitioning the available flash memory and creating the `Memory layout configuration`_. +.. note:: + |file_suffix_partition_manager_exception| + Binaries and images for nRF Cloud FOTA ====================================== diff --git a/doc/nrf/config_and_build/configuring_app/advanced_building.rst b/doc/nrf/config_and_build/configuring_app/advanced_building.rst new file mode 100644 index 00000000000..5ed9eb86ac1 --- /dev/null +++ b/doc/nrf/config_and_build/configuring_app/advanced_building.rst @@ -0,0 +1,40 @@ +.. _building_advanced: + +Advanced building procedures +############################ + +.. contents:: + :local: + :depth: 2 + +You can customize the basic :ref:`building ` procedures in a variety of ways, depending on the configuration of your project. + +.. _compiler_settings: + +Advanced compiler settings +************************** + +The application has full control over the build process. + +Using Zephyr's configuration options is the standard way of controlling how the system is built. +These options can be found under Zephyr's menuconfig **Build and Link Features** > **Compiler Options**. +For example, to turn off optimizations, select :kconfig:option:`CONFIG_NO_OPTIMIZATIONS`. + +Compiler options not controlled by the Zephyr build system can be controlled through the :kconfig:option:`CONFIG_COMPILER_OPT` Kconfig option. + +Optional build parameters +************************* + +Here are some of the possible options you can use: + +* You can provide :ref:`custom CMake options ` to the build command. +* You can include the *directory_name* parameter to build from a directory other than the current directory. +* You can use the *build_target@board_revision* parameter to get extra devicetree overlays with new features available for a board version. + The *board_revision* is printed on the label of your DK, just below the PCA number. + For example, if you run the west build command with an additional parameter ``@1.0.0`` for nRF9160 build target, it adds the external flash on the nRF9160 DK that was available since :ref:`board version v0.14.0 `. +* You can :ref:`start menuconfig with the west command ` to configure your application. +* You can :ref:`reuse an existing build directory ` for building another application for another board or build target by passing ``-p=auto`` to ``west build``. + +For more information on other optional build parameters, run the ``west build -h`` help text command. + +.. |output_files_note| replace:: For more information about files generated as output of the build process, see :ref:`app_build_output_files`. diff --git a/doc/nrf/config_and_build/configuring_app/cmake/index.rst b/doc/nrf/config_and_build/configuring_app/cmake/index.rst new file mode 100644 index 00000000000..39f75586104 --- /dev/null +++ b/doc/nrf/config_and_build/configuring_app/cmake/index.rst @@ -0,0 +1,183 @@ +.. _configuring_cmake: + +Adding files and configuring CMake +################################## + +.. contents:: + :local: + :depth: 2 + +As described in more detail in :ref:`app_build_system`, the Zephyr and |NCS| build systems are based on `CMake `_. +For this reason, every application in Zephyr and the |NCS| must have a :file:`CMakeLists.txt` file. +This file is the entry point of the build system as it specifies the application source files for the compiler to include in the :ref:`configuration phase `. + +Maintaining CMakeLists.txt +************************** + +The recommended method to maintain and update the :file:`CMakeLists.txt` file is to use the |nRFVSC|. +The extension provides support for the `source control with west`_ and `CMake build system`_, including `build configuration management `_ and `source and config files overview
`_. + +.. _modifying_files_compiler: + +Adding source files to CMakeLists.txt +************************************* + +You can add source files to the ``app`` CMake target with the :c:func:`target_sources` function provided by CMake. + +Pay attention to the following configuration options: + +* If your application is complex, you can split it into subdirectories. + These subdirectories can provide their own :file:`CMakeLists.txt` files. + (The main :file:`CMakeLists.txt` file needs to include those.) +* The build system searches for header files in include directories. + Add additional include directories for your application with the :c:func:`target_include_directories` function provided by CMake. + For example, if you want to include an :file:`inc` directory, the code would look like the following: + + .. code-block:: c + + target_include_directories(app PRIVATE inc) + +See :ref:`zephyr:zephyr-app-cmakelists` in the Zephyr documentation for more information about how to edit :file:`CMakeLists.txt`. + +.. note:: + You can also read the `CMake Tutorial`_ in the CMake documentation for a better understanding of how :file:`CMakeLists.txt` are used in a CMake project. + This tutorial however differs from Zephyr and |NCS| project configurations, so use it only as reference. + +.. _cmake_options: +.. _building_overlay_files: + +Providing CMake options +*********************** + +You can provide additional options for building your application to the CMake process, which can be useful, for example, to switch between different build scenarios. +These options are specified when CMake is run, thus not during the actual build, but when configuring the build. + +The |NCS| uses the same CMake build variables as Zephyr and they are compatible with both CMake and west. + +For the complete list of build variables in Zephyr and more information about them, see :ref:`zephyr:important-build-vars` in the Zephyr documentation. +The following table lists the most common ones used in the |NCS|: + +.. list-table:: Build system variables in the |NCS| + :header-rows: 1 + + * - Variable + - Purpose + - CMake argument to use + * - Name of the Kconfig option + - Set the given Kconfig option to a specific value :ref:`for a single build `. + - ``-D=`` + * - :makevar:`EXTRA_CONF_FILE` + - Provide additional :ref:`Kconfig fragment files `. + - ``-DEXTRA_CONF_FILE=.conf`` + * - :makevar:`EXTRA_DTC_OVERLAY_FILE` + - Provide additional, custom :ref:`devicetree overlay files `. + - ``-DEXTRA_DTC_OVERLAY_FILE=.overlay`` + * - :makevar:`SHIELD` + - Select one of the supported :ref:`shields ` for building the firmware. + - ``-DSHIELD=`` + * - :makevar:`FILE_SUFFIX` + - | Select one of the available :ref:`suffixed configurations `, if the application or sample supports any. + | See :ref:`app_build_file_suffixes` for more information about their usage and limitations in the |NCS|. + | This variable is gradually replacing :makevar:`CONF_FILE`. + - ``-DFILE_SUFFIX=`` + * - :makevar:`CONF_FILE` + - | Select one of the available :ref:`build types `, if the application or sample supports any. + | This variable is deprecated and is being gradually replaced by :makevar:`FILE_SUFFIX`, but :ref:`still required for some applications `. + - ``-DCONF_FILE=prj_.conf`` + * - ``-S`` (west) or :makevar:`SNIPPET` (CMake) + - | Select one of the :ref:`zephyr:snippets` to add to the application firmware during the build. + | The west argument ``-S`` is more commonly used. + - | ``-S `` + | ``-DSNIPPET=`` + * - :makevar:`PM_STATIC_YML_FILE` + - Select a :ref:`static configuration file ` for the Partition Manager script. + - ``-DPM_STATIC_YML_FILE=pm_static_.yml`` + +You can use these parameters in both the |nRFVSC| and the command line. + +The build variables are applied one after another, based on the order you provide them. +This is how you can specify them: + +.. tabs:: + + .. group-tab:: nRF Connect for VS Code + + See `How to build an application`_ in the |nRFVSC| documentation. + You can specify the additional configuration variables when `setting up a build configuration `_: + + * :makevar:`FILE_SUFFIX` (and :makevar:`CONF_FILE`) - Select the configuration in the :guilabel:`Configuration` menu. + * :makevar:`EXTRA_CONF_FILE` - Add the Kconfig fragment file in the :guilabel:`Kconfig fragments` menu. + * :makevar:`EXTRA_DTC_OVERLAY_FILE` - Add the devicetree overlays in the :guilabel:`Devicetree overlays` menu. + * Other variables - Provide CMake arguments in the :guilabel:`Extra CMake arguments` field, preceded by ``--``. + + For example, to build the :ref:`location_sample` sample for the nRF9161 DK with the nRF7002 EK Wi-Fi support, select ``nrf9161dk_nrf9161_ns`` in the :guilabel:`Board` menu, :file:`overlay-nrf7002ek-wifi-scan-only.conf` in the :guilabel:`Kconfig fragments` menu, and provide ``-- -DSHIELD=nrf7002ek`` in the :guilabel:`Extra CMake arguments` field. + + .. group-tab:: Command line + + Pass the additional options to the ``west build`` command when :ref:`building`. + The CMake arguments must be added after a ``--`` at the end of the command. + + For example, to build the :ref:`location_sample` sample for the nRF9161 DK with the nRF7002 EK Wi-Fi support, the command would look like follows: + + .. code-block:: + + west build -p -b nrf9161dk_nrf9161_ns -- -DSHIELD=nrf7002ek -DEXTRA_CONF_FILE=overlay-nrf7002ek-wifi-scan-only.conf + +See :ref:`configuration_permanent_change` and Zephyr's :ref:`zephyr:west-building-cmake-args` for more information. + +Examples of commands +-------------------- + +**Providing a CMake variable for build types** + + .. toggle:: + + .. tabs:: + + .. group-tab:: nRF Connect for VS Code + + To select the build type in the |nRFVSC|: + + 1. When `building an application `_ as described in the |nRFVSC| documentation, follow the steps for setting up the build configuration. + #. In the **Add Build Configuration** screen, select the desired :file:`.conf` file from the :guilabel:`Configuration` drop-down menu. + #. Fill in other configuration options, if applicable, and click :guilabel:`Build Configuration`. + + .. group-tab:: Command line + + To select the build type when building the application from command line, specify the build type by adding the following parameter to the ``west build`` command: + + .. parsed-literal:: + :class: highlight + + -- -DCONF_FILE=prj_\ *selected_build_type*\.conf + + For example, you can replace the *selected_build_type* variable to build the ``release`` firmware for ``nrf52840dk_nrf52840`` by running the following command in the project directory: + + .. parsed-literal:: + :class: highlight + + west build -b nrf52840dk_nrf52840 -d build_nrf52840dk_nrf52840 -- -DCONF_FILE=prj_release.conf + + The ``build_nrf52840dk_nrf52840`` parameter specifies the output directory for the build files. + .. + + .. + + If the selected board does not support the selected build type, the build is interrupted. + For example, for the :ref:`nrf_machine_learning_app` application, if the ``nus`` build type is not supported by the selected board, the following notification appears: + + .. code-block:: console + + Configuration file for build type ``nus`` is missing. + + .. + +.. _cmake_options_images: + +Providing CMake options for specific images +=========================================== + +You can prefix the build variable names with the image name if you want the variable to be applied only to a specific image: ``-D_=``. +For example, ``-DEXTRA_CONF_FILE=external_crypto.conf`` will be applied to the default image for which you are building (most often, the application image), while ``-Dmcuboot_EXTRA_CONF_FILE=external_crypto.conf`` will be applied to the MCUboot image. + +This feature is not available for setting Kconfig options. diff --git a/doc/nrf/config_and_build/configuring_app/hardware/index.rst b/doc/nrf/config_and_build/configuring_app/hardware/index.rst new file mode 100644 index 00000000000..a380b406a21 --- /dev/null +++ b/doc/nrf/config_and_build/configuring_app/hardware/index.rst @@ -0,0 +1,26 @@ +.. _configuring_devicetree: + +Configuring devicetree +###################### + +The |nRFVSC| is the recommended tool for editing :ref:`configure_application_hw`. +The extension offers several layers of `Devicetree integration `_, ranging from summarizing devicetree settings in a menu and providing devicetree language support in the editor, to the Devicetree Visual Editor, a GUI tool for editing devicetree files. +Follow the steps in `How to create devicetree files`_ and use one of the following options to edit the :file:`.dts`, :file:`.dtsi`, and :file:`.overlay` files: + +* `Devicetree Visual Editor `_ +* `Devicetree language support`_ + +Like Kconfig fragment files, devicetree files can also be provided as overlays. +The devicetree overlay files are named the same as the build target and use the file extension :file:`.overlay`. +When they are placed in the :file:`boards` folder and the devicetree overlay file name matches the build target, the build system automatically selects and applies the overlay. +To select them manually, see :ref:`cmake_options`. + +The following guides provide information about configuring specific aspects of hardware support related to devicetree. +Read them together with Zephyr's :ref:`zephyr:hardware_support` and :ref:`zephyr:dt-guide` guides, and the official `Devicetree Specification`_. + +.. toctree:: + :maxdepth: 1 + :caption: Subpages: + + pin_control + use_gpio_pin_directly diff --git a/doc/nrf/config_and_build/pin_control.rst b/doc/nrf/config_and_build/configuring_app/hardware/pin_control.rst similarity index 100% rename from doc/nrf/config_and_build/pin_control.rst rename to doc/nrf/config_and_build/configuring_app/hardware/pin_control.rst diff --git a/doc/nrf/config_and_build/use_gpio_pin_directly.rst b/doc/nrf/config_and_build/configuring_app/hardware/use_gpio_pin_directly.rst similarity index 95% rename from doc/nrf/config_and_build/use_gpio_pin_directly.rst rename to doc/nrf/config_and_build/configuring_app/hardware/use_gpio_pin_directly.rst index 2f7c4500b8e..69fea7e5fe3 100644 --- a/doc/nrf/config_and_build/use_gpio_pin_directly.rst +++ b/doc/nrf/config_and_build/configuring_app/hardware/use_gpio_pin_directly.rst @@ -103,8 +103,8 @@ To initialize the defined GPIO pin structures, use the ``GPIO_DT_SPEC_INST_GET_B #include static const struct gpio_dt_spec pin_dbg0 = - GPIO_DT_SPEC_GET_OR(DT_NODELABEL(user_dbg_pin), gpios, 0, {0}); + GPIO_DT_SPEC_GET_BY_IDX_OR(DT_NODELABEL(user_dbg_pin), gpios, 0, {0}); static const struct gpio_dt_spec pin_dbg1 = - GPIO_DT_SPEC_GET_OR(DT_NODELABEL(user_dbg_pin), gpios, 1, {0}); + GPIO_DT_SPEC_GET_BY_IDX_OR(DT_NODELABEL(user_dbg_pin), gpios, 1, {0}); The rest of the GPIO pin operations follow the same process in case of declaring a single pin. diff --git a/doc/nrf/config_and_build/configuring_app/index.rst b/doc/nrf/config_and_build/configuring_app/index.rst new file mode 100644 index 00000000000..0171db9af99 --- /dev/null +++ b/doc/nrf/config_and_build/configuring_app/index.rst @@ -0,0 +1,75 @@ +.. _building: +.. _gs_modifying: +.. _configure_application: + +Configuring and building an application +####################################### + +.. contents:: + :local: + :depth: 2 + +|application_sample_definition| + +After you have :ref:`created an application `, you need to build it in order to be able to program it. +Just as for creating the application, you can build the application using either the |nRFVSC| or the command line. + +.. tabs:: + + .. group-tab:: nRF Connect for VS Code + + For instructions about building with the |nRFVSC|, see `How to build an application`_ in the extension documentation. + + By default, the extension runs both stages of the CMake build (:ref:`configuration phase and building phase `). + If you want to only set up the build configuration without building it, make sure the :guilabel:`Build after generating configuration` is not selected. + + If you want to build with custom options or scripts, read about `Binding custom tasks to actions`_ in the extension documentation. + + .. note:: + |ncs_oot_sample_note| + + |output_files_note| + + .. group-tab:: Command line + + Complete the following steps to build on the command line: + + 1. Open a terminal window. + #. Go to the specific application directory. + + For example, if you want to build the :ref:`at_client_sample` sample, run the following command to navigate to its directory: + + .. code-block:: console + + cd nrf/samples/cellular/at_client + + #. Build the application by using the following west command with the *build_target* specified: + + .. parsed-literal:: + :class: highlight + + west build -b *build_target* + + See :ref:`programming_board_names` for more information on the supported boards and build targets. + The board targets supported for a given application are always listed in its requirements section. + + After running the ``west build`` command, the build files can be found in :file:`build/zephyr`. + |output_files_note| + For more information on the contents of the build directory, see :ref:`zephyr:build-directory-contents` in the Zephyr documentation. + + For more information on building using the command line, see :ref:`Building ` in the Zephyr documentation. + +.. note:: + |application_sample_long_path_windows| + +.. toctree:: + :maxdepth: 1 + :caption: Subpages: + + cmake/index + hardware/index + kconfig/index + advanced_building + output_build_files + +.. |output_files_note| replace:: For more information about files generated as output of the build process, see :ref:`app_build_output_files`. diff --git a/doc/nrf/config_and_build/configuring_app/kconfig/index.rst b/doc/nrf/config_and_build/configuring_app/kconfig/index.rst new file mode 100644 index 00000000000..c68b148afd9 --- /dev/null +++ b/doc/nrf/config_and_build/configuring_app/kconfig/index.rst @@ -0,0 +1,136 @@ +.. _configuring_kconfig: + +Configuring Kconfig +################### + +.. contents:: + :local: + :depth: 2 + +You can change the software-related configuration temporarily or permanently. +The temporary build files are deleted when you clean the build directory with the ``pristine`` target (see Zephyr's :ref:`zephyr:application_rebuild` for more information). + +The :ref:`Kconfig Reference ` provides the documentation for each configuration option and lists the menu path where the option can be found. + +.. _configuration_temporary_change: + +Temporary Kconfig changes +************************* + +When building your application, the different :file:`.config`, :file:`*_defconfig` files, and the :file:`prj.conf` file are merged together and then processed by Kconfig. +The resulting configuration is written to the :file:`zephyr/.config` file in your :file:`build` directory. +This means that this file is available when building the application until you clean the build directory pristinely. + +.. note:: + While it is possible to edit the :file:`.config` file directly, you should use the nRF Kconfig GUI in the |nRFVSC| or a tool like menuconfig or guiconfig to update it. + These tools present all available options and allow you to select the ones that you need. + They also show the dependencies between the options and their limitations. + +.. tabs:: + + .. group-tab:: nRF Connect for VS Code + + Use the nRF Kconfig GUI in the |nRFVSC| to select the desired options. + The GUI organizes the Kconfig options in a hierarchical list and lets you view and manage your selection. + + To locate a specific configuration option, use the **Search modules** field. + Read the `Configuring with nRF Kconfig`_ page in the |nRFVSC| documentation for more information. + + Alternatively, you can configure your application in the |nRFVSC| using menuconfig. + Open the **More actions..** menu next to `Kconfig action in the Actions View`_ to start menuconfig in the extension. + + .. group-tab:: Command line + + To quickly test different configuration options, or to build your application in different variants, you can update the :file:`.config` file in the build directory. + Changes are picked up immediately. + + Alternatively, you can configure your application using menuconfig. + For this purpose, run the following command when :ref:`programming_cmd`. + + .. code-block:: console + + west build -t menuconfig + + See :ref:`zephyr:menuconfig` in the Zephyr documentation for instructions on how to run menuconfig or guiconfig. + To locate a specific configuration option, use the **Jump to** field. + +.. _configuration_temporary_change_single_build: + +Temporary Kconfig changes for a single build +============================================ + +You can also apply temporary Kconfig changes to a single build by :ref:`providing the value of a chosen Kconfig option as a CMake option `. +The Kconfig option configuration will be available until you clean the build directory pristinely. + +.. _configuration_permanent_change: + +Permanent Kconfig changes +************************* + +To configure your application and maintain the configuration after you clean the build directory pristinely, you need to specify the configuration in one of the permanent configuration files. +In most of the cases, this means editing the default :file:`prj.conf` file of the application, but you can also use an extra Kconfig fragment file. + +The Kconfig fragment files are configuration files used for building an application image with or without software support that is enabled by specific Kconfig options. +In these files, you can specify different values for configuration options that are defined by a library or board, and you can add configuration options that are specific to your application. +Examples include whether to add networking support or which drivers are needed by the application. +Kconfig fragments are applied on top of the default :file:`prj.conf` file and use the :file:`.conf` file extension. +When they are board-specific, they are placed in the :file:`boards` folder, are named :file:`.conf`, and they are applied on top of the default Kconfig file for the specified board. + +See :ref:`zephyr:setting_configuration_values` in the Zephyr documentation for information on how to change the configuration permanently and :ref:`how the additional files are applied `. + +.. tip:: + Reconfiguring through menuconfig only changes the specific setting and the invisible options that are calculated from it. + It does not adjust visible symbols that have already defaulted to a value even if this default calculation is supposed to be dependent on the changed setting. + This may result in a bloated configuration compared to changing the setting directly in :file:`prj.conf`. + See the section Stuck symbols in menuconfig and guiconfig on the :ref:`kconfig_tips_and_tricks` in the Zephyr documentation for more information. + +.. tabs:: + + .. group-tab:: nRF Connect for VS Code + + If you work with |nRFVSC|, you can use one of the following options: + + * Edit the :file:`prj.conf` directly in |VSC|. + * Select an extra Kconfig fragment file when you `build an application `_. + * Edit the Kconfig options in :file:`prj.conf` using the nRF Kconfig GUI and save changes permanently to an existing or new :file:`prj.conf` file. + + See the `extension's documentation about Kconfig `_ for more information. + + .. group-tab:: Command line + + If you work on the command line, use one of the following options: + + * Edit the :file:`prj.conf` directly and run the standard ``west build`` command. + * Pass the additional options to the ``west build`` command by adding them after a ``--`` at the end of the command. + + .. ncs-include:: develop/west/build-flash-debug.rst + :docset: zephyr + :start-after: will take effect. + :end-before: To enable :makevar:`CMAKE_VERBOSE_MAKEFILE`, + + See :ref:`zephyr:west-building-cmake-config` for more information. + +The configuration changes in :file:`prj.conf` are automatically picked up by the build system when you rebuild the application. + +.. _kconfig_override_warnings: + +Override Kconfig warnings +************************* + +Kconfig options often depend on each other, and because of this the build system can override any Kconfig changes you make. +If that happens, a warning will be printed in the build log, but the build may still complete successfully. + +Here is an example for such a warning: + +.. code-block:: console + + warning: UART_CONSOLE (defined at drivers/console/Kconfig:43) was assigned the value 'y' but got the + value 'n'. Check these unsatisfied dependencies: SERIAL (=n), SERIAL_HAS_DRIVER (=n). See + http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_UART_CONSOLE and/or look up UART_CONSOLE in + the menuconfig/guiconfig interface. The Application Development Primer, Setting Configuration + Values, and Kconfig - Tips and Best Practices sections of the manual might be helpful too. + +Look for these warnings to make sure no Kconfig options are overridden unexpectedly. + +These warnings might be more frequent if you edit the Kconfig files manually. +The Kconfig GUI and other Kconfig tools give you an overview over dependencies, which allows you to see which Kconfig options have been overridden and why before you build the project. diff --git a/doc/nrf/config_and_build/output_build_files.rst b/doc/nrf/config_and_build/configuring_app/output_build_files.rst similarity index 100% rename from doc/nrf/config_and_build/output_build_files.rst rename to doc/nrf/config_and_build/configuring_app/output_build_files.rst diff --git a/doc/nrf/config_and_build/dfu/dfu_image_versions.rst b/doc/nrf/config_and_build/dfu/dfu_image_versions.rst index 8bf099681ef..40b4c535631 100644 --- a/doc/nrf/config_and_build/dfu/dfu_image_versions.rst +++ b/doc/nrf/config_and_build/dfu/dfu_image_versions.rst @@ -36,7 +36,11 @@ This option can refer to two different things: Configuring image version with MCUboot ************************************** -To assign a semantic version number to your application when you have opted for booting application directly by the MCUboot bootloader (that is, if you have opted for either :ref:`ug_bootloader_adding_immutable_mcuboot` or :ref:`ug_bootloader_adding_upgradable_mcuboot`), add the version string to the :kconfig:option:`CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` option for the application: +To assign a semantic version number to your application when you have opted for booting application directly by the MCUboot bootloader (that is, if you have opted for either :ref:`ug_bootloader_adding_immutable_mcuboot` or :ref:`ug_bootloader_adding_upgradable_mcuboot`), it is recommended to use the :file:`VERSION` file that contains the version information for the application image. +Using a :file:`VERSION` file allows you to independently configure the version value for each build instance of the application. +See Zephyr's :ref:`zephyr:app-version-details` page for more information. + +Alternatively, you can also add the version string to the :kconfig:option:`CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` Kconfig option for the application: .. code-block:: console diff --git a/doc/nrf/config_and_build/dfu/index.rst b/doc/nrf/config_and_build/dfu/index.rst index b5a1b545c43..75e39d74b01 100644 --- a/doc/nrf/config_and_build/dfu/index.rst +++ b/doc/nrf/config_and_build/dfu/index.rst @@ -9,21 +9,46 @@ Device Firmware Updates :depth: 2 Device Firmware Update (DFU) is the procedure of upgrading the application firmware version on a device. -It is composed of two steps. -First a new firmware image is transferred to the chip, and then the :ref:`bootloader ` tests and boots the new firmware. +It consists of two primary steps: -You can transfer the updated images to the device in two ways: +1. Transferring the new firmware - a new firmware image is transferred to the device's chip. -* Wired, where updates are sent through a wired connection, like UART, or delivered by connecting a flash device. -* Over-the-air (OTA), where updates are sent through a wireless connection, like Bluetooth® Low Energy. +#. Testing and booting - the bootloader then tests and boots the new firmware. + +.. note:: + The choice of bootloader affects how firmware updates can be performed. + While bootloader features (such as out-of-the-box support) for various DFU methods may vary, it is recognized that: + + * MCUboot and its supporting libraries and middleware are flexible and support various protocols and methods for firmware updates. + However, the extent of supported features, like USB-DFU class, may vary and should be confirmed with the latest MCUboot documentation or source code. + * The nRF Secure Immutable Bootloader (NSIB) allows for firmware updates but might not include comprehensive support for all types of firmware updates compared to MCUboot. -The testing and booting process depends on the choice of bootloader. + This distinction is crucial for developing your firmware update strategy and selecting the appropriate bootloader for your device's needs. + +Bootloader and application roles in DFU +*************************************** + +The testing and booting process depends on the choice of bootloader and the application design. Generally, bootloaders support two types of updates: * Direct updates, with an in-place substitution of the image. - In this case, it is the bootloader that must transfer the update image. + In this case, the bootloader transfers the update image. * Background updates, where the updated image is obtained and stored by the application, but the update is completed by the bootloader after the device reboots. +In systems that use MCUboot, the application may be responsible for receiving update packages through Simple Management Protocol (SMP) and staging them for the bootloader. +The relation can be explained as follows: + +* The bootloader manages the final steps of the DFU process and has ability to receive, verify, and activate either new or already-received firmware images. +* The application manages firmware updates by receiving and staging new firmware or candidate images, especially when using SMP, and then prepares them for installation by the bootloader. + +Methods of transferring updated images +************************************** + +You can transfer the updated images to the device in two ways: + +* Wired, where updates are sent through a wired connection, like UART, or delivered by connecting a flash device. +* Over-the-air (OTA), where updates are sent through a wireless connection, like Bluetooth® Low Energy. + Based on these criteria, the |NCS| offers support for the following DFU alternatives: * For sending updates to the receiving device: @@ -73,7 +98,15 @@ Based on these criteria, the |NCS| offers support for the following DFU alternat - Library in the |NCS| that provides functions for downloading a firmware file as an upgrade candidate to the DFU target. The library is often used by IoT libraries, such as the :ref:`lib_nrf_cloud` library. - OTA (LTE, Wi-Fi) -See the following user guides for an overview of topics related to firmware updates with the |NCS|: +Device-specific DFU guides +************************** + +See the following pages for device-specific guides related to DFU: + +* :ref:`qspi_xip` - for the nRF5340 SoC +* :ref:`ug_nrf70_fw_patch_update` - for nRF70 Series devices + +See the following user guides for an overview of topics related to general firmware updates with the |NCS|: .. toctree:: :maxdepth: 2 diff --git a/doc/nrf/config_and_build/modifying.rst b/doc/nrf/config_and_build/modifying.rst deleted file mode 100644 index b554644af90..00000000000 --- a/doc/nrf/config_and_build/modifying.rst +++ /dev/null @@ -1,266 +0,0 @@ -.. _gs_modifying: -.. _modifying: - -Modifying an application -######################## - -.. contents:: - :local: - :depth: 2 - -|application_sample_definition| - -After programming and testing an application, you probably want to make some modifications to the application, for example, add your own files with additional functionality, change compilation options, or update the default configuration. - -.. _modifying_files_compiler: - -Adding files and changing compiler settings -******************************************* - -The |NCS| build system is based on Zephyr, whose build system is based on `CMake `_. -For an overview of the build system in the |NCS|, see :ref:`app_build_system`. -For information about how the build system works in Zephyr, see :ref:`zephyr:build_overview` and :ref:`zephyr:application` in the Zephyr documentation. - -Updating CMakeLists.txt -======================= - -The recommended method to update the :file:`CMakeLists.txt` file is to use the |nRFVSC| to maintain it. -You can also edit the file directly. - -Editing CMakeLists.txt -====================== - -You can add source files to the ``app`` CMake target with the :c:func:`target_sources` function provided by CMake. - -Pay attention to the following configuration options: - -* If your application is complex, you can split it into subdirectories. - These subdirectories can provide their own :file:`CMakeLists.txt` files. -* The build system searches for header files in include directories. - Add additional include directories for your application with the :c:func:`target_include_directories` function provided by CMake. - For example, if you want to include an :file:`inc` directory, the code would look like the following: - - .. code-block:: c - - target_include_directories(app PRIVATE inc) - -See the `CMake documentation`_ and :ref:`zephyr:cmake-details` in the Zephyr documentation for more information about how to edit :file:`CMakeLists.txt`. - -Advanced compiler settings -========================== - -The application has full control over the build process. - -Using Zephyr's configuration options is the standard way of controlling how the system is built. -These options can be found under Zephyr's menuconfig **Build and Link Features** > **Compiler Options**. -For example, to turn off optimizations, select :kconfig:option:`CONFIG_NO_OPTIMIZATIONS`. - -Compiler options not controlled by the Zephyr build system can be controlled through the :kconfig:option:`CONFIG_COMPILER_OPT` Kconfig option. - -.. _configure_application: - -Configuring your application -**************************** - -You might want to change the default options of the application for each of its :ref:`configuration systems `. -There are different ways of doing this, but not all will store your configuration permanently. - -Changing the hardware configuration -=================================== - -To correctly edit the :file:`.dts` and :file:`.overlay` files for your project, you need to be familiar with the :ref:`Devicetree language and syntax `. - -.. tabs:: - - .. group-tab:: nRF Connect for VS Code - - The |nRFVSC| offers several layers of `Devicetree integration `_, ranging from summarizing devicetree settings in a menu and providing devicetree language support in the editor, to the Devicetree Visual Editor, a GUI tool for editing devicetree files. - Follow the steps in `How to create devicetree files`_ and use one of the following options to edit the :file:`.dts` and :file:`.overlay` files: - - * `Devicetree Visual Editor `_ - * `Devicetree language support`_ - - -Changing the software configuration -=================================== - -You can change the software-related configuration temporarily or permanently. -The temporary build files are deleted when you clean the build directory with the ``pristine`` target (see Zephyr's :ref:`zephyr:application_rebuild` for more information). - -.. _configuration_temporary_change: - -Temporary changes ------------------ - -When building your application, the different :file:`.config`, :file:`*_defconfig` files and the :file:`prj.conf` file are merged together and then processed by Kconfig. -The resulting configuration is written to the :file:`zephyr/.config` file in your :file:`build` directory. -This means that this file is available when building the application until you clean the build directory pristinely. - -The documentation for each :ref:`configuration option ` lists the menu path where the option can be found. - -.. tabs:: - - .. group-tab:: nRF Connect for VS Code - - Use the nRF Kconfig GUI in the |nRFVSC| to select the desired options. - The GUI organizes the Kconfig options in a hierarchical list and lets you view and manage your selection. - - To locate a specific configuration option, use the **Search modules** field. - Read the `Configuring with nRF Kconfig`_ page in the |nRFVSC| documentation for more information. - - Alternatively, you can configure your application in the |nRFVSC| using menuconfig. - Open the **More actions..** menu next to `Kconfig action in the Actions View`_ to start menuconfig in the extension. - - .. group-tab:: Command line - - To quickly test different configuration options, or to build your application in different variants, you can update the :file:`.config` file in the build directory. - Changes are picked up immediately. - - .. note:: - While it is possible to edit the :file:`.config` file directly, you should use the nRF Kconfig GUI in the |nRFVSC| or a tool like menuconfig or guiconfig to update it. - These tools present all available options and allow you to select the ones that you need. - - Alternatively, you can configure your application using menuconfig. - For this purpose, run the following command when :ref:`programming_cmd`. - - .. code-block:: console - - west build -t menuconfig - - See :ref:`zephyr:menuconfig` in the Zephyr documentation for instructions on how to run menuconfig or guiconfig. - To locate a specific configuration option, use the **Jump to** field. - -.. _configuration_permanent_change: - -Permanent changes ------------------ - -To configure your application and maintain the configuration after you clean the build directory pristinely, you need to specify the configuration in one of the permanent configuration files. -This will be either the default :file:`prj.conf` file of the application or an extra Kconfig fragment. -In these files, you can specify different values for configuration options that are defined by a library or board, and you can add configuration options that are specific to your application. - -See :ref:`zephyr:setting_configuration_values` in the Zephyr documentation for information on how to change the configuration permanently. - -.. tip:: - Reconfiguring through menuconfig only changes the specific setting and the invisible options that are calculated from it. - It does not adjust visible symbols that have already defaulted to a value even if this default calculation is supposed to be dependent on the changed setting. - This may result in a bloated configuration compared to changing the setting directly in :file:`prj.conf`. - See the section Stuck symbols in menuconfig and guiconfig on the :ref:`kconfig_tips_and_tricks` in the Zephyr documentation for more information. - -.. tabs:: - - .. group-tab:: nRF Connect for VS Code - - If you work with |nRFVSC|, you can use one of the following options: - - * Select an extra Kconfig fragment file when you `build an application `_. - * Edit the Kconfig options using the nRF Kconfig GUI and save changes permanently to an existing or new :file:`prj.conf` file. - - See the `extension's documentation about Kconfig `_ for more information. - - .. group-tab:: Command line - - If you work on the command line, pass the additional options to the ``west build`` command. - The options must be added after a ``--`` at the end of the command. - See :ref:`zephyr:west-building-cmake-config` for more information. - -The :file:`prj.conf` file is read when you open a project. -The file will be reloaded when CMake re-runs. -This will happen automatically when the application is rebuilt. - -.. _cmake_options: - -Providing CMake options -*********************** - -You can provide additional options for building your application to the CMake process, which can be useful, for example, to switch between different build scenarios. -These options are specified when CMake is run, thus not during the actual build, but when configuring the build. - -For information about what variables can be set and how to add these variables in your project, see :ref:`zephyr:important-build-vars` in the Zephyr documentation. - -.. tabs:: - - .. group-tab:: nRF Connect for VS Code - - If you work with the |nRFVSC|, you can specify project-specific CMake options when you add the :term:`build configuration` for a new |NCS| project. - See `How to build an application`_ in the |nRFVSC| documentation. - - .. group-tab:: Command line - - If you work on the command line, pass the additional options to the ``west build`` command. - The options must be added after a ``--`` at the end of the command. - See :ref:`zephyr:west-building-cmake-args` for more information. - -.. _gs_modifying_build_types: -.. _modifying_build_types: - -Configuring build types -*********************** - -.. build_types_overview_start - -When the ``CONF_FILE`` variable contains a single file and this file follows the naming pattern :file:`prj_.conf`, then the build type will be inferred to be **. -The build type cannot be set explicitly. -The ** can be any string, but it is common to use ``release`` and ``debug``. - -For information about how to set variables, see :ref:`zephyr:important-build-vars` in the Zephyr documentation. - -The following software components can be made dependent on the build type: - -* The Partition Manager's :ref:`static configuration `. - When the build type has been inferred, the file :file:`pm_static_.yml` will have precedence over :file:`pm_static.yml`. -* The :ref:`child image Kconfig configuration `. - The child image Kconfig overlay file is named :file:`child_image/.conf` instead of :file:`prj.conf`, but otherwise follows the same pattern as the parent Kconfig. - - Alternatively, the child image Kconfig configuration file can be introduced as :file:`child_image//prj.conf` and follow the same pattern as the parent Kconfig. - For example, :file:`child_image/mcuboot/prj_release.conf` can be used to define ``release`` build type for ``mcuboot`` child image. - -.. build_types_overview_end - -The Devicetree configuration is not affected by the build type. - -.. note:: - For an example of an application that is using build types, see the :ref:`nrf_desktop` application (:ref:`nrf_desktop_requirements_build_types`) or the :ref:`nrf_machine_learning_app` application (:ref:`nrf_machine_learning_app_requirements_build_types`). - -.. tabs:: - - .. group-tab:: nRF Connect for VS Code - - .. build_types_selection_vsc_start - - To select the build type in the |nRFVSC|: - - 1. When `building an application `_ as described in the |nRFVSC| documentation, follow the steps for setting up the build configuration. - #. In the **Add Build Configuration** screen, select the desired :file:`.conf` file from the :guilabel:`Configuration` drop-down menu. - #. Fill in other configuration options, if applicable, and click :guilabel:`Build Configuration`. - - .. build_types_selection_vsc_end - - .. group-tab:: Command line - - .. build_types_selection_cmd_start - - To select the build type when building the application from command line, specify the build type by adding the following parameter to the ``west build`` command: - - .. parsed-literal:: - :class: highlight - - -- -DCONF_FILE=prj_\ *selected_build_type*\.conf - - For example, you can replace the *selected_build_type* variable to build the ``release`` firmware for ``nrf52840dk_nrf52840`` by running the following command in the project directory: - - .. parsed-literal:: - :class: highlight - - west build -b nrf52840dk_nrf52840 -d build_nrf52840dk_nrf52840 -- -DCONF_FILE=prj_release.conf - - The ``build_nrf52840dk_nrf52840`` parameter specifies the output directory for the build files. - - .. build_types_selection_cmd_end - -If the selected board does not support the selected build type, the build is interrupted. -For example, for the :ref:`nrf_machine_learning_app` application, if the ``nus`` build type is not supported by the selected board, the following notification appears: - -.. code-block:: console - - Configuration file for build type ``nus`` is missing. diff --git a/doc/nrf/config_and_build/multi_image.rst b/doc/nrf/config_and_build/multi_image.rst index 48ae1d4b861..745bd162ab6 100644 --- a/doc/nrf/config_and_build/multi_image.rst +++ b/doc/nrf/config_and_build/multi_image.rst @@ -50,7 +50,7 @@ nRF5340 Audio development kit support When programming an application for the nRF5340 Audio DK, the application core image is built from a combination of different configuration files. The network core image is programmed with an application-specific precompiled Bluetooth Low Energy Controller binary file that contains the LE Audio Controller Subsystem for nRF53. - See the :ref:`nrf53_audio_app` application documentation for more information. + See the documentation for :ref:`nrf53_audio_app` for more information. .. _ug_multi_image_default_config: @@ -255,7 +255,7 @@ The following example adds an extra Kconfig fragment ``extrafragment.conf`` to ` .. parsed-literal:: :class: highlight - cmake -D\ *childimageone*\_OVERLAY_CONFIG=\ *extrafragment.conf*\ [...] + cmake -D\ *childimageone*\_EXTRA_CONF_FILE=\ *extrafragment.conf*\ [...] It is also possible to provide a custom configuration file as a replacement for the default Kconfig file for the child image. The following example uses the custom configuration file ``myfile.conf`` when building ``childimageone``: @@ -268,20 +268,20 @@ The following example uses the custom configuration file ``myfile.conf`` when bu If your application includes multiple child images, then you can combine all the above as follows: * Setting ``CONFIG_VARIABLEONE=val`` in the main application. -* Adding a Kconfig fragment ``extrafragment.conf`` to the ``childimageone`` child image, using ``-Dchildimageone_OVERLAY_CONFIG=extrafragment.conf``. +* Adding a Kconfig fragment ``extrafragment.conf`` to the ``childimageone`` child image, using ``-Dchildimageone_EXTRA_CONF_FILE=extrafragment.conf``. * Using ``myfile.conf`` as configuration for the ``quz`` child image, using ``-Dquz_CONF_FILE=myfile.conf``. .. parsed-literal:: :class: highlight - cmake -DCONFIG_VARIABLEONE=val -D\ *childimageone*\_OVERLAY_CONFIG=\ *extrafragment.conf*\ -Dquz_CONF_FILE=\ *myfile.conf*\ [...] + cmake -DCONFIG_VARIABLEONE=val -D\ *childimageone*\_EXTRA_CONF_FILE=\ *extrafragment.conf*\ -Dquz_CONF_FILE=\ *myfile.conf*\ [...] See :ref:`ug_bootloader` for more details. .. note:: The build system grabs the Kconfig fragment or configuration file specified in a CMake argument relative to that image's application directory. - For example, the build system uses ``nrf/samples/bootloader/my-fragment.conf`` when building with the ``-Db0_OVERLAY_CONFIG=my-fragment.conf`` option, whereas ``-DOVERLAY_CONFIG=my-fragment.conf`` grabs the fragment from the main application's directory, such as ``zephyr/samples/hello_world/my-fragment.conf``. + For example, the build system uses ``nrf/samples/bootloader/my-fragment.conf`` when building with the ``-Db0_EXTRA_CONF_FILE=my-fragment.conf`` option, whereas ``-DEXTRA_CONF_FILE=my-fragment.conf`` grabs the fragment from the main application's directory, such as ``zephyr/samples/hello_world/my-fragment.conf``. You can also merge multiple fragments into the overall configuration for an image by giving a list of Kconfig fragments as a string, separated using ``;``. The following example shows how to combine ``abc.conf``, Kconfig fragment of the ``childimageone`` child image, with the ``extrafragment.conf`` fragment: @@ -289,7 +289,7 @@ The following example shows how to combine ``abc.conf``, Kconfig fragment of the .. parsed-literal:: :class: highlight - cmake -D\ *childimageone*\_OVERLAY_CONFIG='\ *extrafragment.conf*\;\ *abc.conf*\' + cmake -D\ *childimageone*\_EXTRA_CONF_FILE='\ *extrafragment.conf*\;\ *abc.conf*\' When the build system finds the fragment, it outputs their merge during the CMake build output as follows: @@ -332,7 +332,7 @@ Permanent configuration changes to child images ----------------------------------------------- You can make a project automatically pass Kconfig configuration files, fragments, and devicetree overlays to child images by placing them under a predefined path. -For example, in the |NCS| applications and samples that use different :ref:`build types for configuration `, the :file:`child_image` folder in the application source directory is often used to apply :ref:`permanent configuration changes `. +For example, in the |NCS| applications and samples that use different :ref:`build types `, the :file:`child_image` folder in the application source directory is often used to apply :ref:`permanent configuration changes `. The listing below describes how to leverage this functionality, where ``ACI_NAME`` is the name of the child image to which the configuration will be applied. @@ -341,6 +341,10 @@ The listing below describes how to leverage this functionality, where ``ACI_NAME :start-at: It is possible for a sample to use a custom set of Kconfig fragments for a :end-before: set(ACI_CONF_DIR ${APPLICATION_CONFIG_DIR}/child_image) +When you are using :ref:`app_build_additions_build_types` and the configuration name has been inferred, the child image Kconfig overlay file is searched at :file:`child_image/_.conf`. +Alternatively, the child image Kconfig configuration file can be introduced as :file:`child_image//prj.conf` and follow the same pattern as the parent Kconfig. +For example, :file:`child_image/mcuboot/prj_release.conf` can be used to define the ``release`` build type for the ``mcuboot`` child image. + Child image targets =================== diff --git a/doc/nrf/config_and_build/programming.rst b/doc/nrf/config_and_build/programming.rst index 2ef76e9685a..d3b68ed5650 100644 --- a/doc/nrf/config_and_build/programming.rst +++ b/doc/nrf/config_and_build/programming.rst @@ -1,8 +1,10 @@ .. _gs_programming: .. _programming: +.. _programming_vsc: +.. _programming_cmd: -Building and programming an application -####################################### +Programming an application +########################## .. contents:: :local: @@ -10,124 +12,93 @@ Building and programming an application |application_sample_definition| -For additional information, check the user guide for the hardware platform that you are using. -These user guides contain platform-specific instructions for building and programming. -For example, see :ref:`ug_nrf5340_building` in the :ref:`ug_nrf5340` user guide for information about programming an nRF5340 DK, or :ref:`Programming precompiled firmware images ` and :ref:`building_pgming` for information about programming a Thingy:91. - -.. note:: - |application_sample_long_path_windows| - -.. _programming_vsc: - -Building with |VSC| -******************* - -For instructions about building with the |nRFVSC|, see `How to build an application`_. -If you want to build and program with custom options, read about the advanced `Custom launch and debug configurations`_. - -For information about how to flash and erase in the |nRFVSC|, read about the `Application-specific flash options`_. - -.. note:: - |ncs_oot_sample_note| - -|output_files_note| - -.. _programming_cmd: - -Building on the command line -**************************** - -After completing the :ref:`command-line build setup `, use the following steps to build |NCS| projects on the command line. +To program the :ref:`output build files ` to your device, which in most of the cases will be :file:`zephyr.hex` or :file:`merged.hex`, use the steps for the development environment. -1. Open a terminal window. +.. tabs:: - If you have installed the |NCS| using the :ref:`legacy Toolchain Manager `, click the down arrow next to the version you installed and select :guilabel:`Open bash`. + .. group-tab:: nRF Connect for VS Code - .. figure:: ../installation/images/gs-assistant_tm_dropdown.png - :alt: The Toolchain Manager dropdown menu for the installed nRF Connect SDK version, cropped + You need to set up a build configuration before you program a device in the |nRFVSC|. - The Toolchain Manager dropdown menu options + Complete the following steps: -#. Go to the specific application directory. + 1. Connect the development kit to your PC using a USB cable. + #. Power on the development kit. + #. Make sure you are familiar with :ref:`programming_hw`. + #. Open the nRF Connect extension in |VSC| by clicking its icon in the :guilabel:`Activity Bar`. + #. In the extension's :guilabel:`Actions View`, click on :guilabel:`Flash`. - For example, if you want to build the :ref:`at_client_sample` sample, run the following command to navigate to its directory: + For instructions about programming with the |nRFVSC|, see `How to flash an application`_. - .. code-block:: console + If you want to program with custom options or scripts, read about `Binding custom tasks to actions`_ in the extension documentation. - cd nrf/samples/cellular/at_client + For information about how to flash and erase in the |nRFVSC|, read about the `Application-specific flash options`_. -#. Build the application using the west command. - The build target is specified by the parameter *build_target* in the west command as follows: + .. group-tab:: Command line - .. parsed-literal:: - :class: highlight + Complete the following steps: - west build -b *build_target* + 1. Connect the development kit to your PC using a USB cable. + #. Power on the development kit. + #. Make sure you are familiar with :ref:`programming_hw`. + #. Program the application to the kit using the following command: - See :ref:`programming_board_names` for more information on the supported boards and build targets. - The board targets supported for a given application are always listed in its requirements section. + .. code-block:: console - After running the ``west build`` command, the build files can be found in :file:`build/zephyr`. - |output_files_note| - For more information on the contents of the build directory, see :ref:`zephyr:build-directory-contents` in the Zephyr documentation. + west flash --erase - .. important:: - If you are working with an nRF9160 DK, make sure to select the correct controller before you program the application to your development kit. + This command erases the full flash memory before programming, which is the recommended approach. + If the application depends on other flash memory areas (for example, if it uses the :ref:`zephyr:settings_api` partition where bonding information is stored), erasing the full kit before programming ensures that these areas are updated with the new content. + You can also :ref:`program without erasing `. - Set the **SW10** switch (marked debug/prog) in the **NRF91** position to program the main controller, or in the **NRF52** position to program the board controller. - In nRF9160 DK v0.9.0 and earlier, the switch is called **SW5**. - See the `Device programming section in the nRF9160 DK User Guide`_ for more information. + The ``west flash`` command automatically resets the kit and starts the application. -#. Connect the development kit to your PC using a USB cable. + For more information on programming using the command line, see :ref:`Flashing ` in the Zephyr documentation. - .. note:: - To program the nRF52840 Dongle instead of a development kit, skip the following instructions and follow the programming instructions in :ref:`zephyr:nrf52840dongle_nrf52840`. -#. Power on the development kit. -#. Program the application to the kit using the following command: +.. _programming_hw: - .. code-block:: console +Hardware-specific programming steps +*********************************** - west flash --erase +Some hardware has platform-specific requirements that must be met before you program the device. +For additional information, check the :ref:`user guide for the hardware platform ` that you are using. - This command erases the full flash memory before programming, which is the recommended approach. - If the application depends on other flash memory areas (for example, if it uses the :ref:`zephyr:settings_api` partition where bonding information is stored), erasing the full kit before programming ensures that these areas are updated with the new content. +For example, if you are working with an nRF9160 DK, you need to select the correct position of the :ref:`board controller ` switch **SW10** before you program the application to your development kit. +Programming to Thingy:91 also requires a :ref:`similar step `, but using a different switch (**SW2**). - As an alternative, you can also clear only those flash memory pages that are to be overwritten with the new application. - With such approach, the old data in other areas will be retained. +Programming the nRF52840 Dongle + To program the nRF52840 Dongle instead of a development kit, follow the programming instructions in :ref:`zephyr:nrf52840dongle_nrf52840` or use the `nRF Connect Programmer app `_. - To erase only the areas of flash memory that are required for programming the new application, use the following command: +.. _programming_params: - .. code-block:: console +Optional programming parameters +******************************* - west flash +You can customize the basic ``west flash`` command in a variety of ways. - The ``west flash`` command automatically resets the kit and starts the application. +.. _programming_params_no_erase: -For more information on building and programming using the command line, see the Zephyr documentation on :ref:`zephyr:west-build-flash-debug`. +Programming without ``--erase`` + As an alternative to the recommended ``west flash --erase``, you can also clear only those flash memory pages that are to be overwritten with the new application. + With such approach, the old data in other areas will be retained. -Optional build parameters -========================= + To erase only the areas of flash memory that are required for programming the new application, use the following command: -You can customize the basic ``west build`` command in a variety of ways. -Here are some of the possible options you can use: + .. code-block:: console -* Some applications contain configuration overlay files that enable specific features. - These can be added to the ``west build`` command as follows: + west flash - .. parsed-literal:: - :class: highlight +Programming with ``--recover`` + Several Nordic Semiconductor SoCs or SiPs supported in the |NCS| offer an implementation of the :term:`Access port protection mechanism (AP-Protect)`, a form of readback protection. + To disable the AP-Protect, you must recover your device. + This is particularly important for multi-core devices. - west build -b *build_target* -- -DOVERLAY_CONFIG="overlay-feature1.conf;overlay-feature2.conf" + Use the following command: - See :ref:`configuration_permanent_change` and Zephyr's :ref:`zephyr:west-building-cmake-args` for more information. -* You can include the *directory_name* parameter to build from a directory other than the application directory. -* You can use the *build_target@board_revision* parameter to get extra devicetree overlays with new features available for a board version. - The *board_revision* is printed on the label of your DK, just below the PCA number. - For example, if you run the west build command with an additional parameter ``@1.0.0`` for nRF9160 build target, it adds the external flash on the nRF9160 DK that was available since board version 0.14.0. -* You can :ref:`start menuconfig with the west command ` to configure your application. -* You can reuse an existing build directory for building another application for another board or build target by passing ``-p=auto`` to ``west build``. + .. code-block:: console -For more information on other optional build parameters, run the ``west build -h`` help text command. + west flash --recover -.. |output_files_note| replace:: For more information about files generated as output of the build process, see :ref:`app_build_output_files`. + This command uses ``nrfjprog --recover`` command in the background. + It erases all user available non-volatile memory and disables the readback protection mechanism if enabled. diff --git a/doc/nrf/create_application.rst b/doc/nrf/create_application.rst index 4aab767ed10..2850672aa4f 100644 --- a/doc/nrf/create_application.rst +++ b/doc/nrf/create_application.rst @@ -130,6 +130,7 @@ Use the following steps depending on the application placement: When the application is created, a VS Code prompt appears. #. Click :guilabel:`Open`. This opens the new application and adds it to the :guilabel:`Applications View` in the extension. + At this point, you have created a freestanding application. #. Add the :file:`west.yml` to create a west workspace around the application: a. In the :guilabel:`Welcome View`, click the :guilabel:`Manage SDKs` action. @@ -137,8 +138,8 @@ Use the following steps depending on the application placement: #. Click :guilabel:`Create west workspace`. #. Enter a location for the :file:`west.yml` file that matches the location provided in step 4. #. Select the SDK version for the west workspace. - The west workspace is initialized and the :guilabel:`Manage SDKs` action changes to :guilabel:`Open west manifest`. - #. In the :guilabel:`Applications View`, click the :guilabel:`Run West Update` button to update the workspace modules. + The west workspace is initialized and the :guilabel:`Manage SDKs` action changes to :guilabel:`Manage west workspace`. + #. Click :guilabel:`Manage west workspace` and select :guilabel:`West Update` button to update the workspace modules. You can now start :ref:`configuring and building ` the application. @@ -167,6 +168,9 @@ Use the following steps depending on the application placement: See the `extension documentation `_ for more information about creating freestanding applications in the extension. + .. note:: + You can transform your freestanding application into a workspace application at any moment by completing the step 7 under the Workspace application tab. + .. _creating_cmd: Creating application for use with command line @@ -200,7 +204,7 @@ Use the following steps depending on the application type: .. parsed-literal:: :class: highlight - west init -m https:\ //github.com/*your-name/your-application* *your-app-worskpace* + west init -m https:\ //github.com/*your-name/your-application* *your-app-workspace* #. Go to the *your-app-workspace* directory using the following command pattern: diff --git a/doc/nrf/dev_model_and_contributions/adding_code.rst b/doc/nrf/dev_model_and_contributions/adding_code.rst index db498886aea..5c17dc855ba 100644 --- a/doc/nrf/dev_model_and_contributions/adding_code.rst +++ b/doc/nrf/dev_model_and_contributions/adding_code.rst @@ -124,11 +124,11 @@ This repository showcases the following features of both the |NCS| and Zephyr: * Basic :ref:`Zephyr application ` skeleton * :ref:`Zephyr workspace applications ` * :ref:`West T2 topology ` -* :ref:`Custom boards ` +* :ref:`Custom boards ` * Custom :ref:`devicetree bindings ` * Out-of-tree :ref:`drivers ` * Out-of-tree libraries -* Example CI configuration (using Github Actions) +* Example CI configuration (using GitHub Actions) * Custom :ref:`west extension ` .. example_app_end @@ -162,7 +162,7 @@ This is demonstrated by the following code, that would be placed somewhere in yo - name: nrf repo-path: sdk-nrf remote: ncs - revision: v2.5.1 + revision: v2.6.0 import: true self: path: application @@ -189,7 +189,7 @@ For example: projects: - name: nrf remote: ncs - revision: v2.5.1 + revision: v2.6.0 import: true # Example for how to override a repository in the nRF Connect SDK with your own: - name: mcuboot diff --git a/doc/nrf/dev_model_and_contributions/code_base.rst b/doc/nrf/dev_model_and_contributions/code_base.rst index f804ce85e43..b549c3d752c 100644 --- a/doc/nrf/dev_model_and_contributions/code_base.rst +++ b/doc/nrf/dev_model_and_contributions/code_base.rst @@ -93,7 +93,7 @@ nRF repositories * Usually licensed for use on Nordic products only. nRF repositories are stand-alone and have no upstreams, since they are unique to the |NCS|. - Some examples of repositories of this type are: + Following are some examples of this type of repositories: * `sdk-nrf`_: The main repository for Nordic-developed software. * `sdk-nrfxlib`_: A repository containing linkable libraries developed by Nordic. diff --git a/doc/nrf/dev_model_and_contributions/ncs_distro.rst b/doc/nrf/dev_model_and_contributions/ncs_distro.rst index 7d924e2b27f..a1f02705531 100644 --- a/doc/nrf/dev_model_and_contributions/ncs_distro.rst +++ b/doc/nrf/dev_model_and_contributions/ncs_distro.rst @@ -47,7 +47,7 @@ This approach is essentially identical to the previous one. However, the :ref:`module repository ` you create will not be part of the |NCS| official distribution by default. Instead, you will need to host your own documentation explaining how to add the module you make available to user's :ref:`own manifest `. -An example of this approach is the `Golioth Zephyr SDK`_, which is set up as a `Zephyr module `_ that a user can add to their own manifest. +An example of this approach is the `Golioth Firmware SDK`_, which is set up as a `Zephyr module `_ that a user can add to their own manifest. Providing a west manifest ************************* @@ -56,7 +56,9 @@ Instead of just providing a module repository like in the previous approach, you With this approach, you can import your manifest directly. It will then in turn import the |NCS| `west manifest file`_. -Just like in the previous approach, Golioth provides an example of such a west manifest, `west-ncs.yml `_ along with a `guide document `_. +A good starting point for such an approach is the Nordic-provided `ncs-example-application`_ repository. +It contains all the necessary integration with |NCS| and example functionality (a driver, library, subsystem, test, etc.) to serve as a reference for your own distribution's manifest repository. +Just like in the previous approach, Golioth provides an example of such a west manifest, `west-ncs.yml `_ along with a `guide document `_. Forking the |NCS| ***************** diff --git a/doc/nrf/device_guides.rst b/doc/nrf/device_guides.rst index 37cad49119c..3f0cac3e61f 100644 --- a/doc/nrf/device_guides.rst +++ b/doc/nrf/device_guides.rst @@ -13,6 +13,7 @@ You can also find here guides that are strictly related to hardware features. device_guides/nrf91 device_guides/nrf70 + device_guides/nrf54l device_guides/nrf53 device_guides/nrf52 device_guides/pmic diff --git a/doc/nrf/device_guides/nrf52.rst b/doc/nrf/device_guides/nrf52.rst index c62e1a312a6..6e2cf3f20ef 100644 --- a/doc/nrf/device_guides/nrf52.rst +++ b/doc/nrf/device_guides/nrf52.rst @@ -1,9 +1,63 @@ .. _ug_nrf52_group: +.. _nrf52_supported_boards: Working with nRF52 Series ######################### -The |NCS| provides support for developing on all nRF52 Series devices and contains board definitions for all development kits and reference design hardware. +Zephyr and the |NCS| provide support and contain board definitions for developing on the following nRF52 Series devices: + +.. list-table:: + :header-rows: 1 + + * - DK + - PCA number + - Build target + - Documentation + * - :ref:`zephyr:nrf52840dk_nrf52840` + - PCA10056 + - ``nrf52840dk_nrf52840`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:nrf52840dk_nrf52811` + - PCA10056 + - ``nrf52840dk_nrf52811`` + - `Product Specification `_ + * - :ref:`zephyr:nrf52833dk_nrf52833` + - PCA10100 + - ``nrf52833dk_nrf52833`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:nrf52833dk_nrf52820` + - PCA10100 + - ``nrf52833dk_nrf52820`` + - `Product Specification `_ + * - :ref:`zephyr:nrf52dk_nrf52832` + - PCA10040 + - ``nrf52dk_nrf52832`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:nrf52dk_nrf52810` + - PCA10040 + - ``nrf52dk_nrf52810`` + - `Product Specification `_ + * - :ref:`zephyr:nrf52dk_nrf52805` + - PCA10040 + - ``nrf52dk_nrf52805`` + - `Product Specification `_ + * - :ref:`zephyr:nrf52840dongle_nrf52840` + - PCA10059 + - ``nrf52840dongle_nrf52840`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:nrf21540dk_nrf52840` + - PCA10112 + - ``nrf21540dk_nrf52840`` + - | `Product Specification `_ + +See also :ref:`ug_radio_fem_nrf21540ek` to learn how to use the RF front-end module (FEM) with the nRF52 Series devices. + +.. note:: + Despite being supported in :ref:`Zephyr `, the |NCS| does not support `Nordic Thingy:52`_. .. toctree:: :maxdepth: 2 diff --git a/doc/nrf/device_guides/nrf53.rst b/doc/nrf/device_guides/nrf53.rst index c6c0742caf2..0987060a1a0 100644 --- a/doc/nrf/device_guides/nrf53.rst +++ b/doc/nrf/device_guides/nrf53.rst @@ -3,9 +3,29 @@ Working with nRF53 Series ######################### -The |NCS| provides support for developing on the nRF5340 System on Chip (SoC) using the nRF5340 DK and the Nordic Thingy:53. +Zephyr and the |NCS| provide support and contain board definitions for developing on the following nRF53 Series devices: -|nrf5340_audio_note| +.. list-table:: + :header-rows: 1 + + * - DK + - PCA number + - Build target + - Documentation + * - :ref:`zephyr:nrf5340dk_nrf5340` + - PCA10095 + - ``nrf5340dk_nrf5340`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:nrf5340_audio_dk_nrf5340` + - PCA10121 + - ``nrf5340_audio_dk_nrf5340`` + - | `Hardware Specification `_ + | :ref:`nrf53_audio_app` + * - :ref:`zephyr:thingy53_nrf5340` + - PCA20053 + - ``thingy53_nrf5340`` + - `Hardware Specification `_ .. toctree:: :maxdepth: 2 @@ -13,5 +33,6 @@ The |NCS| provides support for developing on the nRF5340 System on Chip (SoC) us working_with_nrf/nrf53/nrf5340_gs working_with_nrf/nrf53/nrf5340 + working_with_nrf/nrf53/qspi_xip_guide working_with_nrf/nrf53/thingy53_gs working_with_nrf/nrf53/thingy53 diff --git a/doc/nrf/device_guides/nrf54l.rst b/doc/nrf/device_guides/nrf54l.rst new file mode 100644 index 00000000000..d016e252558 --- /dev/null +++ b/doc/nrf/device_guides/nrf54l.rst @@ -0,0 +1,30 @@ +.. _ug_nrf54l: + +Working with nRF54L Series +########################## + +Zephyr and the |NCS| provide support and contain board definitions for developing on the following nRF54L Series devices: + +.. list-table:: + :header-rows: 1 + + * - DK + - PCA number + - Build target + - Documentation + * - :ref:`zephyr:nrf54l15pdk_nrf54l15` + - PCA10156 + - | ``nrf54l15pdk_nrf54l15_cpuapp`` for the PDK revision v0.2.1, AB0-ES7. + | ``nrf54l15pdk_nrf54l15_cpuapp@0.3.0`` for the PDK revision v0.3.0. + - -- + +.. note:: + + The v0.2.1 revision of the nRF54L15 PDK has **Button 3** and **Button 4** connected to GPIO port 2 that do not support interrupts. + The workaround for this issue is enabled by default with the :kconfig:option:`CONFIG_DK_LIBRARY_BUTTON_NO_ISR` Kconfig option, but it increases the overall power consumption of the system. + +.. toctree:: + :maxdepth: 2 + :caption: Subpages: + + working_with_nrf/nrf54l/ug_nrf54l15_gs diff --git a/doc/nrf/device_guides/nrf70.rst b/doc/nrf/device_guides/nrf70.rst index 6a914c95af1..ff918ef1971 100644 --- a/doc/nrf/device_guides/nrf70.rst +++ b/doc/nrf/device_guides/nrf70.rst @@ -3,7 +3,93 @@ Working with nRF70 Series ######################### -The |NCS| provides support for development on the nRF70 Series, using the nRF7002 DK (PCA10143) that includes the Wi-Fi companion IC. +Zephyr and the |NCS| provide support for developing networking applications with Wi-Fi® connectivity using the following nRF70 Series companion IC devices: + +.. list-table:: + :header-rows: 1 + + * - DK or Prototype platform + - Companion module + - PCA number + - Build target + - Documentation + * - nRF7002 DK + - Not applicable + - PCA10143 + - ``nrf7002dk_nrf5340_cpuapp`` + - | `Product Specification `_ + | :ref:`Getting started ` + | `User Guide `_ + * - nRF7001 emulation on nRF7002 DK + - Not applicable + - PCA10143 + - ``nrf7002dk_nrf7001_nrf5340_cpuapp`` + - | `Product Specification `_ + * - :ref:`zephyr:nrf5340dk_nrf5340` + - nRF7002 EK + - PCA10095 + - ``nrf5340dk_nrf5340_cpuapp`` + - | `Product Specification `_ + | :ref:`Getting started ` + | `User Guide `_ + * - :ref:`zephyr:nrf52840dk_nrf52840` + - nRF7002 EK + - PCA10056 + - ``nrf52840dk_nrf52840`` + - | `Product Specification `_ + | :ref:`Getting started ` + | `User Guide `_ + * - :ref:`zephyr:nrf9160dk_nrf9160` + - nRF7002 EK + - PCA10090 + - ``nrf9160dk_nrf9160_ns`` + - | `Product Specification `_ + | :ref:`Getting started ` + | `User Guide `_ + * - :ref:`zephyr:nrf9161dk_nrf9161` + - nRF7002 EK + - PCA10153 + - ``nrf9161dk_nrf9161_ns`` + - | `Product Specification `_ + | `User Guide `_ + * - :ref:`zephyr:thingy53_nrf5340` + - nRF7002 EB + - PCA20053 + - ``thingy53_nrf5340_cpuapp`` + - | :ref:`Getting started ` + | `User Guide `_ + +The following nRF70 Series shields are available and defined in the :file:`nrf/boards/shields` folder: + +.. list-table:: + :header-rows: 1 + + * - Hardware platform + - PCA number + - Build target + - Documentation + * - nRF7002 :term:`Evaluation Kit (EK)` + - PCA63556 + - ``nrf7002ek`` + - | :ref:`Getting started ` + | `User Guide `_ + * - nRF7002 EK with emulated support for the nRF7001 IC + - PCA63556 + - ``nrf7002ek_nrf7001`` + - | :ref:`Getting started ` + | `User Guide `_ + * - nRF7002 EK with emulated support for the nRF7000 IC + - PCA63556 + - ``nrf7002ek_nrf7000`` + - | :ref:`Getting started ` + | `User Guide `_ + * - nRF7002 :term:`Expansion Board (EB)` + - PCA63561 + - ``nrf7002eb`` + - | :ref:`Getting started ` + | `User Guide `_ + +Applications can be developed on the nRF7002 DK (PCA10143), which includes the nRF7002 companion IC, or on boards compatible with the nRF7002 EK (PCA63556) or the nRF7002 EB (PCA63561). .. toctree:: :maxdepth: 2 @@ -11,4 +97,6 @@ The |NCS| provides support for development on the nRF70 Series, using the nRF700 working_with_nrf/nrf70/features working_with_nrf/nrf70/gs + working_with_nrf/nrf70/nrf7002ek_gs + working_with_nrf/nrf70/nrf7002eb_gs working_with_nrf/nrf70/developing/index diff --git a/doc/nrf/device_guides/nrf91.rst b/doc/nrf/device_guides/nrf91.rst index f6d93176ba9..41658a5097a 100644 --- a/doc/nrf/device_guides/nrf91.rst +++ b/doc/nrf/device_guides/nrf91.rst @@ -3,21 +3,40 @@ Working with nRF91 Series ######################### -.. contents:: - :local: - :depth: 2 - -The |NCS| provides support for developing on the following nRF91 Series devices: - -* `nRF9161 System in Package (SiP) `_ using the `nRF9161 DK (PCA10153) `_ -* `nRF9160 System in Package (SiP) `_ using the `nRF9160 DK (PCA10090) `_ -* `Thingy:91 (PCA20035) `_ - -The |NCS| also offers :ref:`samples ` dedicated to these devices. -For more details on the SiPs, see the following guides: - -* nRF9161 - `nRF9161 product website`_ and the `nRF9161 Product Specification`_ -* nRF9160 - `nRF9160 product website`_ and the `nRF9160 Product Specification`_ +Zephyr and the |NCS| provide support for developing cellular applications using the following nRF91 Series devices: + +.. list-table:: + :header-rows: 1 + + * - DK or Prototype platform + - PCA number + - Build target + - Documentation + - Product pages + * - :ref:`zephyr:nrf9161dk_nrf9161` + - PCA10153 + - ``nrf9161dk_nrf9161_ns`` + - | `Product Specification `_ + | `User Guide `_ + - | `nRF9161 DK product page`_ + | `nRF9161 System in Package (SiP) `_ + * - :ref:`zephyr:nrf9160dk_nrf9160` + - PCA10090 + - ``nrf9160dk_nrf9160_ns`` + - | `Product Specification `_ + | :ref:`Getting started ` + | `User Guide `_ + - | `nRF9160 DK product page`_ + | `nRF9160 System in Package (SiP) `_ + * - Thingy91 + - PCA20035 + - ``thingy91_nrf9160_ns`` + - | :ref:`Getting started ` + | `User Guide `_ + - | `Thingy\:91 product page`_ + | `nRF9160 System in Package (SiP) `_ + +The nRF Connect SDK also offers :ref:`samples ` dedicated to these devices. To get started with an nRF9161 DK, complete the steps in the Quick Start app in `nRF Connect for Desktop`_. For more advanced topics related to the nRF9161 DK, see the :ref:`ug_nrf9161` documentation. @@ -25,7 +44,7 @@ For more advanced topics related to the nRF9161 DK, see the :ref:`ug_nrf9161` do If you want to go through a hands-on online training to familiarize yourself with cellular IoT technologies and development of cellular applications, enroll in the `Cellular IoT Fundamentals course`_ in the `Nordic Developer Academy`_. .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :caption: Subpages: working_with_nrf/nrf91/nrf91_features diff --git a/doc/nrf/device_guides/working_with_fem.rst b/doc/nrf/device_guides/working_with_fem.rst index 929ddddf2ed..641ce7aa5ca 100644 --- a/doc/nrf/device_guides/working_with_fem.rst +++ b/doc/nrf/device_guides/working_with_fem.rst @@ -40,7 +40,7 @@ The MPSL library provides the following GPIO interface implementations: * :ref:`ug_radio_fem_nrf21540_spi_gpio` - For the nRF21540 GPIO+SPI implementation that uses a 3-pin interface and an SPI interface with the nRF21540. * :ref:`ug_radio_fem_nrf21540_gpio` - For the nRF21540 GPIO implementation that uses a 3-pin interface with the nRF21540. -* :ref:`ug_radio_fem_skyworks` - For the Simple GPIO implementation that uses a 2-pin interface with the SKY66112-11 device. +* :ref:`ug_radio_fem_skyworks` - For the implementation that uses a 2-pin interface with the SKY66112-11 device and other compatible front-end modules. To use these implementations, your application must use a protocol driver that enables the FEM feature. @@ -437,8 +437,8 @@ The following properties are optional and you can add them to the devicetree nod .. _ug_radio_fem_skyworks: -Adding support for Skyworks front-end module -============================================ +Adding support for front-end modules using Simple GPIO interface +================================================================ You can use the Skyworks range extenders with nRF52 and nRF53 Series devices. SKY66112-11 is one of many FEM devices that support the 2-pin PA/LNA interface. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf52/developing.rst b/doc/nrf/device_guides/working_with_nrf/nrf52/developing.rst index 37b0433f053..d74c9549de2 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf52/developing.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf52/developing.rst @@ -189,7 +189,7 @@ In |NCS|, you can build and program the :zephyr:code-sample:`smp-svr` as any oth .. parsed-literal:: :class: highlight - west build -b *build_target* -- -DOVERLAY_CONFIG=overlay-bt.conf + west build -b *build_target* -- -DEXTRA_CONF_FILE=overlay-bt.conf west flash Make sure to indicate the :file:`overlay-bt.conf` overlay configuration for the Bluetooth transport like in the command example. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf52/features.rst b/doc/nrf/device_guides/working_with_nrf/nrf52/features.rst index cc3dcf0c9d8..5a0f6b639b1 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf52/features.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf52/features.rst @@ -17,63 +17,6 @@ For additional information, see the following documentation: * :ref:`ug_nrf52` for more advanced topics related to the nRF52 Series. * :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. -.. _nrf52_supported_boards: - -Supported boards -**************** - -Devices in the nRF52 Series are supported by these boards in the Zephyr open source project and in |NCS|. - -.. list-table:: - :header-rows: 1 - - * - DK - - PCA number - - Build target - - Documentation - * - :ref:`zephyr:nrf52840dk_nrf52840` - - PCA10056 - - ``nrf52840dk_nrf52840`` - - | `Product Specification `_ - | `User Guide `_ - * - :ref:`zephyr:nrf52840dk_nrf52811` - - PCA10056 - - ``nrf52840dk_nrf52811`` - - `Product Specification `_ - * - :ref:`zephyr:nrf52833dk_nrf52833` - - PCA10100 - - ``nrf52833dk_nrf52833`` - - | `Product Specification `_ - | `User Guide `_ - * - :ref:`zephyr:nrf52833dk_nrf52820` - - PCA10100 - - ``nrf52833dk_nrf52820`` - - `Product Specification `_ - * - :ref:`zephyr:nrf52dk_nrf52832` - - PCA10040 - - ``nrf52dk_nrf52832`` - - | `Product Specification `_ - | `User Guide `_ - * - :ref:`zephyr:nrf52dk_nrf52810` - - PCA10040 - - ``nrf52dk_nrf52810`` - - `Product Specification `_ - * - :ref:`zephyr:nrf52dk_nrf52805` - - PCA10040 - - ``nrf52dk_nrf52805`` - - `Product Specification `_ - * - :ref:`zephyr:nrf52840dongle_nrf52840` - - PCA10059 - - ``nrf52840dongle_nrf52840`` - - | `Product Specification `_ - | `User Guide `_ - * - :ref:`zephyr:nrf21540dk_nrf52840` - - PCA10112 - - ``nrf21540dk_nrf52840`` - - `Product Specification `_ - -See :ref:`ug_radio_fem_nrf21540ek` to learn how to use this RF front-end module (FEM) with the nRF52 Series devices. - Secure bootloader chain *********************** diff --git a/doc/nrf/device_guides/working_with_nrf/nrf52/gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf52/gs.rst index c8d433f2777..90145295e91 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf52/gs.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf52/gs.rst @@ -59,8 +59,8 @@ Installing the required software On your computer, install `nRF Connect for Desktop`_. After installing and starting the application, install the Programmer app. -You must also install a terminal emulator, such as :ref:`PuTTY ` or the nRF Terminal, which is part of the `nRF Connect for Visual Studio Code`_ extension. -The steps detailed in :ref:`nrf52_gs_connecting` use PuTTY, but any terminal emulator will work. +You must also install a terminal emulator, such as `nRF Connect Serial Terminal`_, the nRF Terminal (part of the `nRF Connect for Visual Studio Code`_ extension), or PuTTY. +nRF Connect Serial Terminal is the recommended method for :ref:`nrf52_gs_connecting`. On your mobile device, install the `nRF Connect for Mobile`_ application from the corresponding application store. @@ -115,8 +115,7 @@ To program the precompiled sample to your development kit, complete the followin .. program_dk_sample_end -After you have programmed the sample to the DK, you can connect to it and test the functions. -If you connect to the sample now, you can go directly to Step 2 of :ref:`nrf52_gs_connecting`. +After you have programmed the sample to the DK, you can connect to it using a terminal emulator and test the functions. .. _nrf52_gs_connecting: @@ -134,64 +133,11 @@ This is different from communication through the Nordic UART Service (NUS) over If you have problems connecting to the sample, restart the DK and start over. -To connect using CDC-UART, complete the following steps: - -1. Connect the |DK| to the computer with a micro-USB cable, and then turn on the DK. - - **LED1** starts blinking. - -#. Open a terminal emulator; this guide uses PuTTY. - - The **PuTTY Configuration** window opens and the **Session** category is chosen in the category selection tree on the left. - -#. Select **Serial** as the **Connection type** under **Basic options for your PuTTY session**. - - The text fields above the selection change to **Serial line** and **Speed**. - -#. Click the **Terminal** category in the category selection tree to see options controlling the terminal. -#. Enable the following options: - - * Implicit CR in every LF - * Implicit LF in every CR - * Local echo: Force on - * Local line editing: Force on - - .. figure:: ../../../test_and_optimize/images/putty.svg - :alt: PuTTY configuration for sending commands through UART - - PuTTY configuration for sending commands through UART - -#. Click the **Serial** category under the **Connection** category in the category selection tree to see options controlling the local serial line. -#. Type the COM port corresponding to your DK in the **Serial line to connect to** field. - - Depending on what devices you have connected to your computer, you might have several choices. - To find the correct port (in Windows): - - a. Right-click on the Windows Start menu, and select **Device Manager**. - #. In the **Device Manager** window, scroll down and expand **Ports (COM & LPT)**. - #. Find the port named *JLink CDC UART Port* and note down the number in parentheses. - - If you have more than one J-Link UART Port, unplug the one that you want to use, plug it back in, and observe which one appeared last. - - Your DK can show up as two consecutive COM ports. - If this is the case, you need to test which COM port is the correct one. - -#. Configure the following settings in the **Configure the serial line** section: - - * **Speed (baud):** 115200 - * **Data bits:** 8 - * **Stop bits:** 1 - * **Parity:** None - * **Flow control:** RTS/CTS - -#. Click :guilabel:`Open`. - - The terminal window opens. +To connect using CDC-UART, complete the steps listed on the :ref:`test_and_optimize` page for the chosen terminal emulator. .. uart_dk_connect_end -The connection has now been established. -If you test the sample now, you can go directly to Step 2 of :ref:`nrf52_gs_testing`. +Once the connection has been established, continue to :ref:`nrf52_gs_testing`. .. _nrf52_gs_testing: @@ -209,10 +155,7 @@ To perform tests, complete the following steps: .. group-tab:: Android - 1. Connect the |DK| to the computer with a micro-USB cable and turn on the DK. - - **LED1** starts blinking. - + 1. Make sure the |DK| is connected to the computer with a micro-USB cable and has been turned on (**LED1** is blinking). #. Open the nRF Connect for Mobile application on your Android device. #. In nRF Connect for Mobile, tap :guilabel:`Scan`. #. Find the DK in the list, select it and tap :guilabel:`Connect`. @@ -241,10 +184,7 @@ To perform tests, complete the following steps: .. group-tab:: iOS - 1. Connect the |DK| to the computer with a micro-USB cable and turn on the DK. - - **LED1** starts blinking. - + 1. Make sure the |DK| is connected to the computer with a micro-USB cable and has been turned on (**LED1** is blinking). #. Open the nRF Connect for Mobile application on your iOS device. #. If the application does not automatically start scanning, tap the **Play** icon in the upper right corner. #. Find the DK in the list and tap the corresponding :guilabel:`Connect` button. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf53/images/nrf5340_static_partition_manager_slots.svg b/doc/nrf/device_guides/working_with_nrf/nrf53/images/nrf5340_static_partition_manager_slots.svg new file mode 100644 index 00000000000..2298c9c2ce7 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf53/images/nrf5340_static_partition_manager_slots.svg @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + QSPI_XIP + + + + + + + + Nordic Blue.1020 + + + + Nordic Blue.1019 + + + + Sheet.2 + Max 750 px + + + + + Max 750 px + + Sheet.3 + Max 700 px + + + + + Max 700 px + + Sheet.4 + + + + Sheet.5 + + + + Nordic Blue.1000 + + + + Nordic Blue.1001 + + + + Nordic Blue.1002 + + + + Nordic Blueslate.1008 + mcuboot_primary + + + + mcuboot_primary + + Nordic Blueslate.1010 + mcuboot_primary_2 + + + + mcuboot_primary_2 + + Nordic Blueslate.1012 + mcuboot_secondary_2 + + + + mcuboot_secondary_2 + + Nordic Blueslate.1013 + mcuboot_secondary + + + + mcuboot_secondary + + Sheet.1004 + Image 0 + + + + Image 0 + + Sheet.1005 + Image 1 + + + + Image 1 + + Sheet.1006 + Image 2 + + + + Image 2 + + Sheet.1014 + Internal flash + + + + Internal flash + + Sheet.1016 + QSPI XIP + + + + QSPI XIP + + Sheet.1017 + Slot 1 + + + + Slot 1 + + Sheet.1018 + Slot 2 + + + + Slot 2 + + Sheet.1021 + Application processor + + + + Application processor + + Sheet.1022 + Network processor + + + + Network processor + + Nordic Blueslate.1009 + mcuboot_secondary_1 + + + + mcuboot_secondary_1 + + Nordic Blueslate.1011 + mcuboot_primary_1 + + + + mcuboot_primary_1 + + Sheet.1025 + Network core update + + + + Network core update + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340.rst b/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340.rst index 446be6f3465..6005240039e 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340.rst @@ -22,9 +22,9 @@ If you are not familiar with the |NCS| and its development environment, see :ref See the `nRF Connect SDK v1.4.0 documentation`_ for the last release supporting the nRF5340 PDK. -|nrf5340_audio_note| -Given its complexity, the application uses custom building and programming procedures. -Refer to its documentation for more information. +The |NCS| includes :ref:`nrf53_audio_app`, which integrate the LE Audio standard with custom reference hardware based on the nRF5340 DK. +Given their complexity, the applications use custom building and programming procedures. +Refer to their documentation for more information. .. _ug_nrf5340_intro: @@ -517,9 +517,7 @@ See the following instructions. .. group-tab:: west - Enter the following command to recover both cores:: - - west flash --recover + Use the ``--recover`` parameter with ``west flash``, as described in :ref:`programming_params`. .. group-tab:: nrfjprog @@ -539,6 +537,7 @@ See the following instructions. Therefore, you must recover the network core first. Otherwise, if you recover the application core first and the network core last, the binary written to the application core is deleted and readback protection is enabled again after a reset. +.. _ug_nrf53_developing_ble_fota: .. include:: ../nrf52/developing.rst :start-after: fota_upgrades_intro_start :end-before: fota_upgrades_intro_end @@ -595,11 +594,14 @@ To enable the simultaneous update of multiple images in the MCUboot, set the fol * :kconfig:option:`CONFIG_PCD_APP` - Enable commands exchange with the network core. * :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER` - Enable support for multiple update partitions by setting this option to ``2``. +As described in :ref:`multi-image build guide `, make sure to add the child image prefix to the name of Kconfig options that are used when building MCUboot as a child image (for example, ``child_image_CONFIG_PCD_APP``). +If not changed, then the default child image prefix for MCUboot is ``mcuboot_`` (for example, ``mcuboot_CONFIG_PCD_APP``). + .. note:: - The application core can be reverted, but doing so bricks the network core upon revertion, as the reversion process fills the network core with the content currently in the RAM that pcd uses. - To enable this, define the ``USE_NRF53_MULTI_IMAGE_WITHOUT_UPGRADE_ONLY`` Kconfig option in the project-level Kconfig file. - When this is option is defined, you can enable it by setting :kconfig:option`CONFIG_USE_NRF53_MULTI_IMAGE_WITHOUT_UPGRADE_ONLY`. + The application core can be reverted, but doing so breaks the network core upon reversal, as the reversion process fills the network core with the content currently in the RAM that PCD uses. + To enable this, define the :kconfig:option:`CONFIG_USE_NRF53_MULTI_IMAGE_WITHOUT_UPGRADE_ONLY` Kconfig option in the project-level Kconfig file. + When this option is defined, you can enable it by setting :kconfig:option:`CONFIG_USE_NRF53_MULTI_IMAGE_WITHOUT_UPGRADE_ONLY`. The :kconfig:option:`CONFIG_NRF53_MULTI_IMAGE_UPDATE` option selects this feature by default if these options and all its other dependencies are asserted. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340_gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340_gs.rst index 7343e344ce2..a91e663c8c6 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340_gs.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf53/nrf5340_gs.rst @@ -54,8 +54,8 @@ Installing the required software On your computer, install `nRF Connect for Desktop`_. After installing and starting the application, install the Programmer app. -You must also install a terminal emulator, such as :ref:`PuTTY ` or the nRF Terminal, which is part of the `nRF Connect for Visual Studio Code`_ extension. -The steps detailed in :ref:`nrf5340_gs_connecting` use PuTTY, but any terminal emulator will work. +You must also install a terminal emulator, such as `nRF Connect Serial Terminal`_, the nRF Terminal (part of the `nRF Connect for Visual Studio Code`_ extension), or PuTTY. +nRF Connect Serial Terminal is the recommended method for :ref:`nrf5340_gs_connecting`. On your mobile device, install the `nRF Connect for Mobile`_ application from the corresponding application store. @@ -76,8 +76,7 @@ The archive contains the HEX file used to program the sample to your DK. :start-after: program_dk_sample_start :end-before: program_dk_sample_end -After you have programmed the sample to the DK, you can connect to it and test the functions. -If you connect to the sample now, you can go directly to Step 2 of :ref:`nrf5340_gs_connecting`. +After you have programmed the sample to the DK, you can connect to it using a terminal emulator and test the functions. .. _nrf5340_gs_connecting: @@ -88,8 +87,7 @@ Connecting to the sample :start-after: uart_dk_connect_start :end-before: uart_dk_connect_end -The connection has now been established. -If you test the sample now, you can go directly to Step 2 of :ref:`nrf5340_gs_testing`. +Once the connection has been established, continue to :ref:`nrf5340_gs_testing`. .. _nrf5340_gs_testing: diff --git a/doc/nrf/device_guides/working_with_nrf/nrf53/qspi_xip_guide.rst b/doc/nrf/device_guides/working_with_nrf/nrf53/qspi_xip_guide.rst new file mode 100644 index 00000000000..0b48fc240ad --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf53/qspi_xip_guide.rst @@ -0,0 +1,343 @@ +.. _qspi_xip: + +Configuring external XIP +######################## + +.. contents:: + :local: + :depth: 2 + +This guide describes the external execute in place (XIP) support for the nRF5340 SoC. +The nRF5340 SoC is equipped with a Quad Serial Peripheral Interface (QSPI) memory interface, which is capable of exposing QSPI flash as memory for the CPU used to fetch and execute the program code. +The QSPI is available for the application core. +Therefore, it is possible to relocate a part of the application's code to an external memory. +NCS supports dividing an application into an internal and external part, along with the MCUboot support. + +Enabling configuration options +****************************** + +Application configuration must support an external XIP and image splitting. + +Enable the following options: + +* :kconfig:option:`CONFIG_CODE_DATA_RELOCATION` +* :kconfig:option:`CONFIG_HAVE_CUSTOM_LINKER_SCRIPT` +* :kconfig:option:`CONFIG_BUILD_NO_GAP_FILL` +* :kconfig:option:`CONFIG_XIP` +* :kconfig:option:`CONFIG_NORDIC_QSPI_NOR_XIP` +* :kconfig:option:`CONFIG_XIP_SPLIT_IMAGE` +* :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` - This option enables the MCUboot build and support for the application. + +Additionally, set the following options: + +* :kconfig:option:`CONFIG_CUSTOM_LINKER_SCRIPT` to ``""`` +* :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER` to ``3`` +* :kconfig:option:`CONFIG_FLASH_INIT_PRIORITY` to ``40`` - You must ensure the QSPI device initialization priority, as it makes the external XIP code accessible before it is executed. + If any initialization code is expected to be run from the QSPI XIP, then its initialization priority value must be lower than the QSPI device initialization priority. + +Setting up QSPI flash +********************* + +The QSPI flash DTS must be available for the application and the MCUboot. +You must correctly set up the QSPI flash chip in the board devicetree file, including the operating mode. +The flash chip does not have to run in the QSPI mode for XIP to function, but using other modes will reduce the execution speed of the application. + +See the following snippet for an example of the Nordic Thingy:53 configuration that supports DSPI: + +.. code-block:: devicetree + + &qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; + mx25r64: mx25r6435f@0 { + compatible = "nordic,qspi-nor"; + reg = <0>; + writeoc = "pp2o"; + readoc = "read2io"; + 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>; + }; + }; + +.. note:: + Due to QSPI peripheral product anomaly, the QSPI peripheral must be ran with the ``HFCLK192MCTRL=0`` setting. + Any other value may cause undefined operation of the device. + +Add the following to the DTS overlay for your board: + +.. code-block:: devicetree + + / { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; + }; + +Setting up static partition manager +*********************************** + +You need to complete the setup in order to use a static partitioning in your project. +The configuration must have 3 images with 2 slots each: + +.. figure:: images/nrf5340_static_partition_manager_slots.svg + :alt: Static partitioning slots in the nRF5340 SoC + + Static partitioning slots in the nRF5340 SoC. + +* The first set of slots is for the internal flash part of the application. + These slots should be named ``mcuboot_primary`` and ``mcuboot_secondary``. +* The second set of slots is for the network core update. + These slots should be named ``mcuboot_primary_1`` and ``mcuboot_secondary_1``. +* The third set of slots is for the QSPI XIP part of the application. + These slots should be named ``mcuboot_primary_2`` and ``mcuboot_secondary_2``. + +This means a basic dual image configuration for the nRF5340 DK needs to describe an external QSPI XIP code partition as ``mcuboot_primary_2`` partition. +Additionally, ensure that: + +* The ``mcuboot_primary_2`` address is expressed as the QSPI flash physical address. +* The ``device`` field is the QSPI device name. +* The ``region`` field is set as ``external_flash``. + +See the following snippet for an example of the static configuration for partition manager: + +.. code-block:: console + + app: + address: 0x10200 + end_address: 0xe4000 + region: flash_primary + size: 0xd3e00 + external_flash: + address: 0x120000 + device: MX25R64 + end_address: 0x800000 + region: external_flash + size: 0x6e0000 + mcuboot: + address: 0x0 + end_address: 0x10000 + region: flash_primary + size: 0x10000 + mcuboot_pad: + address: 0x10000 + end_address: 0x10200 + region: flash_primary + size: 0x200 + mcuboot_primary: + address: 0x10000 + end_address: 0xf0000 + orig_span: &id001 + - mcuboot_pad + - app + region: flash_primary + size: 0xe0000 + span: *id001 + mcuboot_primary_1: + address: 0x0 + device: flash_ctrl + end_address: 0x40000 + region: ram_flash + size: 0x40000 + mcuboot_primary_app: + address: 0x10200 + end_address: 0xf0000 + orig_span: &id002 + - app + region: flash_primary + size: 0xdfe00 + span: *id002 + mcuboot_secondary: + address: 0x0 + device: MX25R64 + end_address: 0xe0000 + region: external_flash + size: 0xe0000 + mcuboot_secondary_1: + address: 0xe0000 + device: MX25R64 + end_address: 0x120000 + region: external_flash + size: 0x40000 + mcuboot_primary_2: + address: 0x120000 + device: MX25R64 + end_address: 0x160000 + region: external_flash + size: 0x40000 + mcuboot_secondary_2: + address: 0x160000 + device: MX25R64 + end_address: 0x1a0000 + region: external_flash + size: 0x40000 + otp: + address: 0xff8100 + end_address: 0xff83fc + region: otp + size: 0x2fc + pcd_sram: + address: 0x20000000 + end_address: 0x20002000 + region: sram_primary + size: 0x2000 + ram_flash: + address: 0x40000 + end_address: 0x40000 + region: ram_flash + size: 0x0 + rpmsg_nrf53_sram: + address: 0x20070000 + end_address: 0x20080000 + placement: + before: + - end + region: sram_primary + size: 0x10000 + settings_storage: + address: 0xf0000 + end_address: 0x100000 + region: flash_primary + size: 0x10000 + sram_primary: + address: 0x20002000 + end_address: 0x20070000 + region: sram_primary + size: 0x6e000 + +Configuring linker script +************************* + +To relocate code to the external flash, you need to configure a linker script. +The script needs to describe the ``EXTFLASH`` flash memory block to which the code will be linked. +The ``ORIGIN`` of the area can be calculated using following elements: + +* The QSPI memory starting with the 0x10000000 internal memory address. +* The offset of an external application part image within the QSPI flash. + The external application code partition is mapped by the ``mcuboot_primary_2`` PM partition. +* The image header size of the MCUboot image (0x200). + +See the following example of the calculation: + +.. code-block:: console + + #include + #include + #include + #include + + MEMORY + { + /* This maps in mcuboot_primary_2 partition defined in pm_static.yaml + * components for ORIGIN calculation: + * - 0x10000000: offset of QSPI external memory in SoC memory mapping. + * - 0x120000: mcuboot_primary_2 offset in QSPI external memory + * - 0x200: image header size. + * The size of this region is size of mcuboot_primary_2 reduced by the + * image header size. + */ + EXTFLASH (wx) : ORIGIN = 0x10120200, LENGTH = 0x3FE00 + } + + #include + +Setting up code relocation +************************** + +Relocating code to QSPI XIP is a part of the project's :file:`CMakeLists.txt` file. +You can set up the relocation on a file or library basis using the ``zephyr_code_relocate()`` function. +For example, to relocate a file in the application, use the following configuration: + +.. code-block:: console + + zephyr_code_relocate(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth.c LOCATION EXTFLASH_TEXT NOCOPY) + zephyr_code_relocate(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth.c LOCATION RAM_DATA) + +where the first line relocates the XIP code (.text) and the second line relocates the data initialization content section (.data). + +Similarly, it is possible to relocate certain libraries, for example: + +.. code-block:: console + + zephyr_code_relocate(LIBRARY subsys__mgmt__mcumgr__mgmt LOCATION EXTFLASH_TEXT NOCOPY) + zephyr_code_relocate(LIBRARY subsys__mgmt__mcumgr__mgmt LOCATION RAM_DATA) + +Flashing the project +******************** + +For the nRF5340 DK and other boards equipped with flash working in the QSPI mode, use the ``west flash`` command. +For other cases, flashing needs to be done manually. + +Flashing to external flash in SPI/DSPI mode +=========================================== + +Flashing an application with ``west`` triggers the ``nrfjprog`` runner. +The runner uses the default system settings that configure the application in the QSPI mode when flashing the external flash. +You can change this behavior by using a custom :file:`Qspi.ini` configuration file, however, it will prevent flashing through west. + +.. note:: + The :file:`Qspi.ini` file is required to work on the Nordic Thingy:53. + +If you wish to use the :file:`Qspi.ini` file, you will need to manually flash the HEX files in the repository. +For example, for the :ref:`smp_svr_ext_xip` sample, you need to flash the following files (paths are relative to the build directory): + +* :file:`/zephyr/merged_CPUNET.hex` + * For Bluetooth stack application the path is :file:` hci_ipc`. +* :file:`mcuboot/zephyr/zephyr.hex` +* :file:`zephyr/internal_flash_signed.hex` +* :file:`zephyr/qspi_flash_signed.hex` + +Use the following commands to flash and verify the Simple Management Protocol (SMP) server sample: + +.. code-block:: console + + nrfjprog -f NRF53 --coprocessor CP_NETWORK --sectorerase --program hci_ipc/zephyr/merged_CPUNET.hex --verify + nrfjprog -f NRF53 --sectorerase --program mcuboot/zephyr/zephyr.hex --verify + nrfjprog -f NRF53 --sectorerase --program zephyr/internal_flash_signed.hex --verify + nrfjprog -f NRF53 --qspisectorerase --program zephyr/qspi_flash_signed.hex --qspiini /Qspi.ini --verify + nrfjprog -f NRF53 --reset + +.. note:: + The external flash chip must be connected to the dedicated QSPI peripheral port pins of the nRF5340 SoC. + It is not possible to program an external flash chip that is connected to different pins using nrfjprog. + +Troubleshooting +*************** + +Refer to the following sections for information on how to solve the most common issues. + +Module does not appear to start +=============================== + +When using QSPI XIP, a frequent issue is the module not starting or crashing before the application runs. +This often results from a mismatch in ``init`` priorities between the code on QSPI flash and the QSPI flash device. + +To debug this issue, you can use a debugger such as GNU Debugger (GDB) to single-step through the application code until a QSPI address is encountered. +The backtrace functionality can then show which part of the code is responsible for the issue, and you can adjust the ``init`` priority of that module accordingly. + +Given that the QSPI flash ``init`` priority defaults to ``41`` at the ``POST_KERNEL`` level, take into account the following points: + +* There should be no QSPI flash residing code that has an ``init`` priority value that is less than or equal to the ``POST_KERNEL`` level ``41``. +* No interrupt handlers in the QSPI flash should be enabled until the QSPI flash driver has been initialized. + +Module does not boot after update +================================= + +This issue can occur if there is a mismatch between the internal flash code and the QSPI XIP code. +Both slots must be running the same build to successfully boot. +The application will fail to boot in the following cases: + +* If one of the updates is not loaded. +* If a different build is loaded to one of the slots. +* If one of the loaded updates is corrupt and deleted. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/cpuapp_include_tree.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/cpuapp_include_tree.svg new file mode 100644 index 00000000000..60434de94a1 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/cpuapp_include_tree.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + Page-1 + + Nordic Sky + nrf54h20dk_nrf54h20_cpuapp.dts + + nrf54h20dk_nrf54h20_cpuapp.dts + + Nordic Sky.11 + nrf54h20dk_nrf54h20_cpuapp-pinctrl.dtsi + + nrf54h20dk_nrf54h20_cpuapp-pinctrl.dtsi + + Nordic Sky.12 + nrf54h20_cpuapp.dtsi + + nrf54h20_cpuapp.dtsi + + Nordic Sky.14 + nrf54h20.dtsi + + nrf54h20.dtsi + + Nordic Sky.15 + nrf54h20_shared_memory_*.dtsi + + nrf54h20_shared_memory_*.dtsi + + Nordic Sky.16 + haltium_cpuapp_common.dtsi + + haltium_cpuapp_common.dtsi + + Nordic Sky.17 + haltium_cpuapp_local.dtsi + + haltium_cpuapp_local.dtsi + + Nordic Sky.18 + haltium_cpuapp_peripherals.dtsi + + haltium_cpuapp_peripherals.dtsi + + Nordic Sky.19 + nrf_common.dtsi + + nrf_common.dtsi + + Nordic Sky.20 + haltium_global_peripherals.dtsi + + haltium_global_peripherals.dtsi + + Nordic Sky.21 + haltium_global_peripherals_virtual.dtsi + + haltium_global_peripherals_virtual.dtsi + + Nordic Sky.23 + haltium_tdd_peripherals.dtsi + + haltium_tdd_peripherals.dtsi + + Dynamic connector + + + + Dynamic connector.27 + + + + Dynamic connector.28 + + + + Dynamic connector.29 + + + + Dynamic connector.30 + + + + Dynamic connector.32 + + + + Dynamic connector.33 + + + + Dynamic connector.34 + + + + Dynamic connector.35 + + + + Dynamic connector.36 + + + + Dynamic connector.37 + + + + Nordic Blue + ic-next/boards/<arch> ic-next/dts/common ic-next/dts/<arch> + + ic-next/boards/<arch> ic-next/dts/common ic-next/dts/<arch> + + Nordic Lake + + + + Nordic Sun + + + + Nordic Grass + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_Domains.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_Domains.svg new file mode 100644 index 00000000000..1017b6faf0b --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_Domains.svg @@ -0,0 +1,96 @@ + + + + + + + + Page-1 + + Nordic Lake.8 + Radio Core + + Radio Core + + Nordic Sky.9 + CPU + + CPU + + Nordic Sky.10 + Multiprotocol 2.4 GHz Radio + + Multiprotocol 2.4 GHz Radio + + Nordic Lake.14 + Application Core + + Application Core + + Nordic Sky.15 + CPU + + CPU + + Nordic Lake.19 + Global Domain + + Global Domain + + Nordic Sky.20 + RAM + + RAM + + Nordic Sky.21 + NVM + + NVM + + Nordic Sky.22 + Peripherals + + Peripherals + + Nordic Lake.23 + Secure Domain + + Secure Domain + + Nordic Sky.24 + Secure Boot + + Secure Boot + + Nordic Sky.25 + Secure Storage + + Secure Storage + + Nordic Sky.26 + Physical Security + + Physical Security + + Nordic Sky.28 + Crypto Accelerators + + Crypto Accelerators + + Dynamic connector + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_appcore.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_appcore.svg new file mode 100644 index 00000000000..20859171103 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_appcore.svg @@ -0,0 +1,60 @@ + + + + + + + + Page-1 + + Nordic Lake + + + + Nordic Sky + Arm Cortex-M33 Max 320 MHz DVFS L1 I-Cache, L1 D-Cache Trustz... + + Arm Cortex-M33 Max 320 MHz DVFS L1 I-Cache, L1 D-Cache Trustzone, FPU, DSP + + Nordic Sky.9 + MVDMA + + MVDMA + + Nordic Sky.10 + SPU + + SPU + + Nordic Sky.11 + MPC + + MPC + + Nordic Sky.12 + IPC + + IPC + + Nordic Sky.13 + 2x WDT + + 2x WDT + + Nordic Sky.14 + 32 KB RAM + + 32 KB RAM + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_bootsequence.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_bootsequence.svg new file mode 100644 index 00000000000..30b21537b41 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_bootsequence.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + Page-1 + + Nordic Lake.1003 + Primary boot stage + + Primary boot stage + + Nordic Lake.1004 + Secondary boot stage + + Secondary boot stage + + Nordic Blue + System Controller ROM + + System Controller ROM + + Nordic Sky + Calibrate MRAM from OTP Re-calibrate system from FICR once MR... + + · Calibrate MRAM from OTP · Re-calibrate system from FICR once MRAM is up + + Nordic Blue.7 + Secure Domain ROM + + Secure Domain ROM + + Nordic Sky.8 + Verify secure domain firmware Move PUF keys to CRACEN Authent... + + · Verify secure domain firmware · Move PUF keysto CRACEN · Authenticated erase + + Nordic Blue.9 + Secure Domain firmware + + Secure Domain firmware + + Nordic Sky.10 + Configure global resources Control access port(s) Verify syst... + + · Configure global resources · Control access port(s) · Verify system controller firmware · Verify local cares firmware · Secure servicesfor local cores + + Nordic Blue.11 + System Controller firmware + + System Controller firmware + + Nordic Sky.12 + Global services for local cores + + · Global servicesfor local cores + + Nordic Blue.13 + Radio Core + + Radio Core + + Nordic Blue.27 + Application Core + + Application Core + + Event.1005 + + + Dynamic connector.1006 + + + + Dynamic connector.1007 + + + + Dynamic connector.1008 + + + + Dynamic connector.1009 + + + + Dynamic connector.1010 + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_globaldomain.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_globaldomain.svg new file mode 100644 index 00000000000..2b37c0634bb --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_globaldomain.svg @@ -0,0 +1,311 @@ + + + + + + + + Page-1 + + Nordic Blue + High-Speed + + High-Speed + + Nordic Blue.10 + Low-Leakage + + Low-Leakage + + Nordic Blueslate + Memories + + Memories + + Nordic Blueslate.14 + Peripherals + + Peripherals + + Nordic Blue.17 + SRAM 768 KB + + SRAM 768 KB + + Nordic Blue.18 + MRAM 1024 KB + + MRAM 1024 KB + + Nordic Blue.19 + MRAM 1024 KB + + MRAM 1024 KB + + Nordic Blue.20 + ROM + + ROM + + Nordic Lake + Peripheral Handling (optional) Software-defined peripherals + + Peripheral Handling (optional) Software-defined peripherals + + Nordic Blue.27 + HS-SPIM + + HS-SPIM + + Nordic Blue.28 + HS-SPIS + + HS-SPIS + + Nordic Blue.29 + HS-SPIM / UART + + HS-SPIM / UART + + Nordic Blue.30 + HS-USB + + HS-USB + + Nordic Blue.31 + 2x I3C + + 2x I3C + + Nordic Blue.32 + HS-PWM + + HS-PWM + + Nordic Blue.33 + 2x Timer + + 2x Timer + + Nordic Blue.34 + 128 KB RAM + + 128 KB RAM + + Nordic Blue.35 + FLPR CPU + + FLPR CPU + + Nordic Blueslate.36 + Configuration and control + + Configuration and control + + Nordic Blueslate.37 + + + + Nordic Blue.38 + SPU + + SPU + + Nordic Blue.39 + IPCT + + IPCT + + Nordic Blue.40 + MPC + + MPC + + Nordic Blue.41 + DDPIC + + DDPIC + + Nordic Blue.42 + 100 MHz 1.8 V GPIO Port + + 100 MHz 1.8 V GPIO Port + + Nordic Blue.43 + 200 MHz 1.8 V GPIO Port + + 200 MHz 1.8 V GPIO Port + + Nordic Blueslate.45 + Peripherals + + Peripherals + + Nordic Lake.46 + Peripheral Handling (optional) + + Peripheral Handling (optional) + + Nordic Blue.47 + Global RTC + + Global RTC + + Nordic Blue.48 + 8x SPI/TWI/UART + + 8x SPI/TWI/UART + + Nordic Blue.49 + 8x Timer + + 8x Timer + + Nordic Blue.50 + 14-bit ADC + + 14-bit ADC + + Nordic Blue.51 + 4x 4ch PWM + + 4x 4ch PWM + + Nordic Blue.52 + PDM + + PDM + + Nordic Blue.53 + Audio PLL + + Audio PLL + + Nordic Blue.54 + 80 KB RAM + + 80 KB RAM + + Nordic Blue.55 + PPR CPU + + PPR CPU + + Nordic Blueslate.56 + Configuration and control + + Configuration and control + + Nordic Blueslate.57 + + + + Nordic Blue.58 + SPU + + SPU + + Nordic Blue.59 + IPCT + + IPCT + + Nordic Blue.60 + MPC + + MPC + + Nordic Blue.61 + DDPIC + + DDPIC + + Nordic Blue.62 + 1.8 – 3.6 V GPIO Port + + 1.8 –V GPIO Port + + Nordic Blue.63 + 3x 1.2 – 1.8 V GPIO Port + + 3x 1.2 –V GPIO Port + + Nordic Blue.64 + COMP + + COMP + + Nordic Blue.65 + SIMIF + + SIMIF + + Nordic Blue.66 + NFC A-Tag + + NFC A-Tag + + Nordic Blue.67 + CAN + + CAN + + Nordic Blue.68 + LPCOMP + + LPCOMP + + Nordic Blue.69 + 2x QDEC + + 2x QDEC + + Nordic Blue.70 + 2x I2S / 2x TDM + + 2x I2S / 2x TDM + + Nordic Blue.71 + IRQMAP + + IRQMAP + + Nordic Blue.72 + IPCMAP + + IPCMAP + + Nordic Blue.1000 + HS-USB + + HS-USB + + Nordic Blue.1001 + 2x I3C + + 2x I3C + + Nordic Blue.1002 + HS-PWM + + HS-PWM + + Nordic Blue.1003 + 2x Timer + + 2x Timer + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_lifecycle_states.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_lifecycle_states.svg new file mode 100644 index 00000000000..f4eb8068d3d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_lifecycle_states.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Light Grey.37 + Production + + Production + + Nordic Light Grey.36 + End-of-life + + End-of-life + + Nordic Light Grey.35 + In-field + + In-field + + Nordic Blue + DISCARDED + + DISCARDED + + Nordic Blue.16 + ANALYSIS + + ANALYSIS + + Nordic Blue.17 + DEPLOYED + + DEPLOYED + + Nordic Blue.18 + RoT + + RoT + + Nordic Blue.19 + EMPTY + + EMPTY + + Dynamic connector + + + + Dynamic connector.21 + + + + Dynamic connector.22 + + + + Dynamic connector.23 + + + + Dynamic connector.24 + + + + Dynamic connector.25 + + + + Dynamic connector.26 + + + + Dynamic connector.28 + + + + Dynamic connector.31 + + + + Dynamic connector.32 + + + + Dynamic connector.33 + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_memorymap.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_memorymap.svg new file mode 100644 index 00000000000..e64cca1ca19 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_memorymap.svg @@ -0,0 +1,394 @@ + + + + + + + + Page-1 + + Rectangle.27 + Internal data memory (non-secure) + + Internal data memory (non-secure) + + Rectangle.6 + Secure alias of internal data memory region + + Secure alias of internal data memory region + + Rectangle.33 + Peripherals (non-secure) + + Peripherals (non-secure) + + Rectangle.35 + Secure alias of peripherals region + + Secure alias of peripherals region + + Rectangle.38 + Global Domain EXMIF (unencrypted view of external memory) + + Global Domain EXMIF (unencrypted view of external memory) + + Rectangle.40 + Global Domain EXMEE (encrypted alias of external memory) + + Global Domain EXMEE (encrypted alias of external memory) + + Rectangle.44 + STM trace + + STM trace + + Rectangle.46 + Peripherals accessible to all masters + + Peripherals accessible to all masters + + Rectangle.48 + Global Trace&Debug Components + + Global Trace&Debug Components + + Rectangle.50 + Peripherals accessible to a specific CPU + + Peripherals accessible to a specific CPU + + Rectangle.52 + Cortex-M System PPB + + Cortex-M System PPB + + Rectangle.54 + System Vendor_SYS + + System Vendor_SYS + + Sheet.18 + 0xFFFF_FFFF + + 0xFFFF_FFFF + + Rectangle.22 + Internal program memory (non-secure) + + Internal program memory (non-secure) + + Rectangle.23 + Secure alias of internal program memory region + + Secure alias of internal program memory region + + Sheet.1012 + 0xF000_0000 + + 0xF000_0000 + + Sheet.1013 + 0xE100_0000 + + 0xE100_0000 + + Sheet.1014 + 0xE000_0000 + + 0xE000_0000 + + Sheet.1015 + 0xC100_0000 + + 0xC100_0000 + + Sheet.1016 + 0xBF00_0000 + + 0xBF00_0000 + + Sheet.1017 + 0xA000_0000 + + 0xA000_0000 + + Sheet.1018 + 0x8000_0000 + + 0x8000_0000 + + Sheet.1019 + 0x6000_0000 + + 0x6000_0000 + + Sheet.1020 + 0x4000_0000 + + 0x4000_0000 + + Sheet.1021 + 0x3000_0000 + + 0x3000_0000 + + Sheet.1022 + 0x2000_0000 + + 0x2000_0000 + + Sheet.1023 + 0x1000_0000 + + 0x1000_0000 + + Sheet.1024 + 0x0000_0000 + + 0x0000_0000 + + Sheet.1025 + 0x5000_0000 + + 0x5000_0000 + + Rectangle.1026 + Secure Domain’s local peripherals + + Secure Domain’s local peripherals + + Rectangle.1027 + Application Core’s local peripherals + + Application Core’s local peripherals + + Rectangle.1028 + Radio Core’s local peripherals + + Radio Core’s local peripherals + + Rectangle.1029 + + + + Rectangle.1030 + Global Domain’s global peripherals + + Global Domain’s global peripherals + + Rectangle.1032 + Memory reserved for local aliases + + Memory reserved for local aliases + + Rectangle.1033 + Memory reserved for Secure Domain PROGMEM + + Memory reserved for Secure Domain PROGMEM + + Rectangle.1034 + Memory reserved for Application Core PROGMEM + + Memory reserved for Application Core PROGMEM + + Rectangle.1035 + Memory reserved for Radio Core PROGMEM + + Memory reserved for Radio Core PROGMEM + + Rectangle.1036 + + + + Rectangle.1037 + Global Domain’s program memory (MRAM) + + Global Domain’s program memory (MRAM) + + Rectangle.1038 + Memory reserved for local aliases + + Memory reserved for local aliases + + Rectangle.1039 + Secure Domain local RAM + + Secure Domain local RAM + + Rectangle.1040 + Application Core local RAM + + Application Core local RAM + + Rectangle.1041 + Radio Core local RAM + + Radio Core local RAM + + Rectangle.1042 + + + + Rectangle.1043 + Global Domain’s global peripherals + + Global Domain’s global peripherals + + Rectangle.1044 + Memory reserved for local aliases + + Memory reserved for local aliases + + Sheet.1045 + 0x5000_0000 + + 0x5000_0000 + + Sheet.1046 + 0x4F00_0000 + + 0x4F00_0000 + + Sheet.1047 + 0x4300_0000 + + 0x4300_0000 + + Sheet.1048 + 0x4200_0000 + + 0x4200_0000 + + Sheet.1049 + 0x4100_0000 + + 0x4100_0000 + + Sheet.1050 + 0x4000_0000 + + 0x4000_0000 + + Sheet.1052 + 0x1000_0000 + + 0x1000_0000 + + Sheet.1053 + 0x0E00_0000 + + 0x0E00_0000 + + Sheet.1054 + 0x0400_0000 + + 0x0400_0000 + + Sheet.1055 + 0x0300_0000 + + 0x0300_0000 + + Sheet.1056 + 0x0200_0000 + + 0x0200_0000 + + Sheet.1057 + 0x0100_0000 + + 0x0100_0000 + + Sheet.1058 + 0x0000_0000 + + 0x0000_0000 + + Sheet.1059 + 0x3000_0000 + + 0x3000_0000 + + Sheet.1060 + 0x2F00_0000 + + 0x2F00_0000 + + Sheet.1062 + 0x2300_0000 + + 0x2300_0000 + + Sheet.1063 + 0x2200_0000 + + 0x2200_0000 + + Sheet.1064 + 0x2100_0000 + + 0x2100_0000 + + Sheet.1065 + 0x2000_0000 + + 0x2000_0000 + + Sheet.1073 + + + + Sheet.1074 + + + + Sheet.1075 + + + + Sheet.1076 + 0xB000_0000 + + 0xB000_0000 + + Sheet.1077 + 0x4400_0000 + + 0x4400_0000 + + Sheet.1078 + 0x2400_0000 + + 0x2400_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_radiocore.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_radiocore.svg new file mode 100644 index 00000000000..5ec0ec33022 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF54H20_radiocore.svg @@ -0,0 +1,88 @@ + + + + + + + + Page-1 + + Nordic Lake + + + + Nordic Sky + Arm Cortex-M33 256 MHz Fast Start-Stop L1 I-Cache, L1 D-Cache... + + Arm Cortex-M33 256 MHz Fast Start-StopL1 I-Cache, L1 D-CacheTrustZone, FPU, DSP + + Nordic Sky.11 + Multiprotocol 2.4 GHz Radio Bluetooth Low Energy Bluetooth LE... + + Multiprotocol2.4 GHz Radio Bluetooth Low EnergyBluetooth LE Audio Bluetooth mEsh IEEE 802.15.42.4 GHz proprietary protocols + + Nordic Sky.13 + 192 KB RAM + + 192 KB RAM + + Nordic Sky.14 + MVDMA + + MVDMA + + Nordic Sky.15 + AES-128 + + AES-128 + + Nordic Sky.16 + RTC + + RTC + + Nordic Sky.17 + 2x WDT + + 2x WDT + + Nordic Sky.18 + DPPI + + DPPI + + Nordic Sky.19 + Timer + + Timer + + Nordic Sky.20 + MPC + + MPC + + Nordic Sky.21 + SPU + + SPU + + Nordic Sky.22 + IPC + + IPC + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF7002ek.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF7002ek.png new file mode 100644 index 00000000000..aa376586de6 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nRF7002ek.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_IPC_layers.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_IPC_layers.svg new file mode 100644 index 00000000000..019f21f9daf --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_IPC_layers.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + Page-1 + + Nordic Blue + Communication libraries + + Communication libraries + + Nordic Blue.6 + IPC service library (ipc_service) + + IPC service library (ipc_service) + + Nordic Blue.7 + IPC transport library (icmsg) + + IPC transport library (icmsg) + + Nordic Blue.8 + Shared RAM + + Shared RAM + + Nordic Blue.17 + Signaling hardware + + Signaling hardware + + Sheet.18 + Presentation layer Application layer + + Presentation layer Application layer + + Sheet.20 + Session layer + + Session layer + + Sheet.21 + Transport layer + + Transport layer + + Sheet.22 + Physical layer + + Physical layer + + Dynamic connector + + + + Dynamic connector.27 + + + + Dynamic connector.28 + + + + Dynamic connector.29 + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_arm_to_vpr.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_arm_to_vpr.svg new file mode 100644 index 00000000000..6fd59c15f38 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_arm_to_vpr.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + Page-1 + + Nordic Lake.9 + Global Domain + + Global Domain + + Nordic Blue.1001 + PPR + + PPR + + Nordic Lake + Application Core + + Application Core + + Nordic Sky + RAM shared buffers + + RAM shared buffers + + Nordic Blue + Peripherals + + Peripherals + + Nordic Sky.11 + BELLBOARD Application Core + + BELLBOARD Application Core + + Nordic Sky.14 + VEVIF + + VEVIF + + Dynamic connector + + + + Dynamic connector.18 + + + + Dynamic connector.19 + + + + Dynamic connector.21 + + + + Dynamic connector.25 + + + + Nordic Blue.27 + + + + Dynamic connector.28 + + + + Dynamic connector.29 + + + + Sheet.28 + BUS system IRQ system + + BUS system IRQ system + + Nordic Sky.1000 + VPR core + + VPR core + + Dynamic connector.1002 + + + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_cpu_to_cpu.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_cpu_to_cpu.svg new file mode 100644 index 00000000000..8bf4beb6202 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_cpu_to_cpu.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Lake + Application Core + + Application Core + + Nordic Lake.7 + Radio Core + + Radio Core + + Nordic Lake.8 + Secure Domain + + Secure Domain + + Nordic Lake.9 + Global Domain + + Global Domain + + Nordic Sky + RAM shared buffers + + RAM shared buffers + + Nordic Blue + Peripherals + + Peripherals + + Nordic Sky.12 + BELLBOARD Application Core + + BELLBOARD Application Core + + Nordic Sky.13 + BELLBOARD Radio Core + + BELLBOARD Radio Core + + Nordic Sky.14 + BELLBOARD Secure Domain + + BELLBOARD Secure Domain + + Dynamic connector + + + + Dynamic connector.17 + + + + Dynamic connector.18 + + + + Dynamic connector.19 + + + + Dynamic connector.20 + + + + Dynamic connector.21 + + + + Dynamic connector.22 + + + + Dynamic connector.23 + + + + Dynamic connector.24 + + + + Dynamic connector.25 + + + + Dynamic connector.26 + + + + Nordic Blue.27 + + + + Dynamic connector.28 + + + + Dynamic connector.29 + + + + Sheet.30 + BUS system IRQ system + + BUS system IRQ system + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.png new file mode 100644 index 00000000000..744683cd57b Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.svg new file mode 100644 index 00000000000..cb7f8d76927 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_app.svg @@ -0,0 +1,48 @@ + + + + + + + + Page-1 + + Rectangle.1000 + Free memory + + Free memory + + Rectangle.1001 + Application Core’s non-secure data (optional, planned) + + Application Core’s non-secure data (optional, planned) + + Rectangle.1002 + Application Core’s secure data + + Application Core’s secure data + + Sheet.1003 + 0x2200_8000 + + 0x2200_8000 + + Sheet.1006 + 0x2200_0000 + + 0x2200_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_bbproc.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_bbproc.svg new file mode 100644 index 00000000000..d46b0c22e74 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_bbproc.svg @@ -0,0 +1,46 @@ + + + + + + + + Page-1 + + Rectangle.1014 + BBPROC data + + BBPROC data + + Rectangle.1015 + BBPROC code + + BBPROC code + + Rectangle.1020 + BBPROC ↔ Radio Core IPC shared memory + + BBPROC ↔ Radio Core IPC shared memory + + Sheet.1027 + 0x2301_8000 + + 0x2301_8000 + + Sheet.1032 + 0x2301_1000 + + 0x2301_1000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.png new file mode 100644 index 00000000000..387e74596cf Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.svg new file mode 100644 index 00000000000..693f5ff6b4c --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram10.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + Page-1 + + Rectangle.40 + System Controller's and Secure Domain’s code and data + + System Controller's and Secure Domain’s code and data + + Rectangle.44 + Radio Core's secure code + + Radio Core's secure code + + Rectangle.46 + Radio Core's secure/non-secure callable + + Radio Core's secure/non-secure callable + + Rectangle.48 + Radio Core's non-secure code + + Radio Core's non-secure code + + Rectangle.50 + Application Core's secure code + + Application Core's secure code + + Rectangle.52 + Application Core's secure/non-secure callable + + Application Core's secure/non-secure callable + + Rectangle.54 + Application Core's non-secure code + + Application Core's non-secure code + + Dynamic connector.56 + May extend to MRAM_11 + + May extend to MRAM_11 + + Sheet.1000 + 0x0E10_0000 + + 0x0E10_0000 + + Sheet.1001 + 0x0E05_4000 + + 0x0E05_4000 + + Sheet.1003 + 0x0E00_0000 + + 0x0E00_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.png new file mode 100644 index 00000000000..87422cdebe2 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.svg new file mode 100644 index 00000000000..1eb8a4e2bb8 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_mram11.svg @@ -0,0 +1,59 @@ + + + + + + + + Page-1 + + Rectangle.27 + Application Core's non-secure code (planned) + + Application Core's non-secure code (planned) + + Rectangle.30 + Application Core's non-volatile storage + + Application Core's non-volatile storage + + Rectangle.33 + Radio Core's non-volatile storage + + Radio Core's non-volatile storage + + Rectangle.54 + Secure Domain's non-volatile storage (planned) + + Secure Domain's non-volatile storage (planned) + + Rectangle.55 + DFU storage bank + + DFU storage bank + + Sheet.1017 + 0x0E20_0000 + + 0x0E20_0000 + + Sheet.1018 + 0x0E10_0000 + + 0x0E10_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.png new file mode 100644 index 00000000000..b1262cf2422 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.svg new file mode 100644 index 00000000000..b79cce65c31 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_radio.svg @@ -0,0 +1,48 @@ + + + + + + + + Page-1 + + Rectangle.1000 + Free memory + + Free memory + + Rectangle.1001 + Radio Core’s non-secure data (optional, planned) + + Radio Core’s non-secure data (optional, planned) + + Rectangle.1002 + Radio Core’s secure data + + Radio Core’s secure data + + Sheet.1003 + 0x2301_8000 + + 0x2301_8000 + + Sheet.1004 + 0x2300_0000 + + 0x2300_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.png new file mode 100644 index 00000000000..510e9f00231 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.svg new file mode 100644 index 00000000000..52df0e78635 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram0x.svg @@ -0,0 +1,90 @@ + + + + + + + + Page-1 + + Rectangle.5 + Free memory + + Free memory + + Rectangle.1 + Secure Domain ↔ Application Core IPC shared memory + + Secure Domain ↔ Application Core IPC shared memory + + Rectangle.7 + Secure Domain's secure data + + Secure Domain's secure data + + Rectangle.10 + Application Core's secure data + + Application Core's secure data + + Rectangle.11 + Radio Core's non-secure data (optional, planned) + + Radio Core's non-secure data (optional, planned) + + Rectangle.18 + Secure Domain ↔ Radio Core IPC shared memory + + Secure Domain ↔ Radio Core IPC shared memory + + Rectangle.20 + Radio Core's secure data (planned) + + Radio Core's secure data (planned) + + Rectangle.22 + Application Core ↔ Radio Core IPC shared memory + + Application Core ↔ Radio Core IPC shared memory + + Rectangle.24 + Application Core's non-secure data (optional, planned) + + Application Core's non-secure data (optional, planned) + + Rectangle.26 + Secure Domain's non-secure data (planned) + + Secure Domain's non-secure data (planned) + + Sheet.1000 + 0x2F0E_0000 + + 0x2F0E_0000 + + Sheet.1001 + 0x2F00_0000 + + 0x2F00_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.png new file mode 100644 index 00000000000..627552f3c79 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.svg new file mode 100644 index 00000000000..8c6cced60f9 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram20.svg @@ -0,0 +1,155 @@ + + + + + + + + Page-1 + + Rectangle.1 + System Controller data + + System Controller data + + Rectangle.7 + System Controller code + + System Controller code + + Rectangle.12 + System Controller’s ROM data + + System Controller’s ROM data + + Rectangle.13 + System Controller → Radio Core IPC shared memory + + System Controller → Radio Core IPC shared memory + + Rectangle.15 + System Controller ← Radio Core IPC shared memory + + System Controller ← Radio Core IPC shared memory + + Rectangle.17 + Radio Core’s mngMBOX (planned) + + Radio Core’s mngMBOX (planned) + + Rectangle.19 + System Controller → Application Core IPC shared memory + + System Controller → Application Core IPC shared memory + + Rectangle.21 + System Controller ← Application Core IPC shared memory + + System Controller ← Application Core IPC shared memory + + Rectangle.23 + Application Core’s mngMBOX (planned) + + Application Core’s mngMBOX (planned) + + Rectangle.25 + System Controller → Secure Domain IPC shared memory + + System Controller → Secure Domain IPC shared memory + + Rectangle.27 + System Controller ← Secure Domain IPC shared memory + + System Controller ← Secure Domain IPC shared memory + + Rectangle.31 + System Controller’s mngMBOX (planned) + + System Controller’s mngMBOX (planned) + + Sheet.1001 + 0x2F89_0000 + + 0x2F89_0000 + + Sheet.1002 + 0x2F88_FF00 + + 0x2F88_FF00 + + Sheet.1003 + 0x2F88_FE80 + + 0x2F88_FE80 + + Sheet.1004 + 0x2F88_FE00 + + 0x2F88_FE00 + + Sheet.1005 + 0x2F88_FDE0 + + 0x2F88_FDE0 + + Sheet.1006 + 0x2F88_FD60 + + 0x2F88_FD60 + + Sheet.1007 + 0x2F88_FCE0 + + 0x2F88_FCE0 + + Sheet.1008 + 0x2F88_FCC0 + + 0x2F88_FCC0 + + Sheet.1009 + 0x2F88_FC40 + + 0x2F88_FC40 + + Sheet.1010 + 0x2F88_FBC0 + + 0x2F88_FBC0 + + Sheet.1011 + 0x2F88_FBA0 + + 0x2F88_FBA0 + + Sheet.1012 + 0x2F88_BBA0 + + 0x2F88_BBA0 + + Sheet.1013 + 0x2F88_0000 + + 0x2F88_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.png new file mode 100644 index 00000000000..8a6de2af67b Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.svg new file mode 100644 index 00000000000..59140520e4d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram21.svg @@ -0,0 +1,59 @@ + + + + + + + + Page-1 + + Rectangle.5 + Free memory + + Free memory + + Rectangle.1 + FLPR data (planned) + + FLPR data (planned) + + Rectangle.7 + FLPR code (planned) + + FLPR code (planned) + + Rectangle.12 + FLPR ↔ Application Core IPC shared memory (planned) + + FLPR ↔ Application Core IPC shared memory (planned) + + Rectangle.16 + EasyDMA buffers for fast peripherals: CAN, UARTE, SPI, I3C + + EasyDMA buffers for fast peripherals: CAN, UARTE, SPI, I3C + + Sheet.1000 + 0x2F89_8000 + + 0x2F89_8000 + + Sheet.1001 + 0x2F89_0000 + + 0x2F89_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.png new file mode 100644 index 00000000000..5f38546b351 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.svg new file mode 100644 index 00000000000..a0ff0b9838d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_ram3x.svg @@ -0,0 +1,63 @@ + + + + + + + + Page-1 + + Rectangle.1013 + Free memory + + Free memory + + Rectangle.1014 + PPR data + + PPR data + + Rectangle.1015 + PPR code + + PPR code + + Rectangle.1020 + PPR ↔ Application Core IPC shared memory + + PPR ↔ Application Core IPC shared memory + + Rectangle.1022 + Radio Core's EasyDMA buffers + + Radio Core's EasyDMA buffers + + Rectangle.1024 + Application Core's EasyDMA buffers for slow peripherals + + Application Core's EasyDMA buffers for slow peripherals + + Sheet.1027 + 0x2FC0_8000 + + 0x2FC0_8000 + + Sheet.1032 + 0x2FC0_0000 + + 0x2FC0_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.png new file mode 100644 index 00000000000..3d1cfbd347d Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.svg new file mode 100644 index 00000000000..aabcca969c1 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memory_map_secure.svg @@ -0,0 +1,36 @@ + + + + + + + + Page-1 + + Rectangle.1001 + Secure Domain’s data + + Secure Domain’s data + + Sheet.1010 + 0x2100_8000 + + 0x2100_8000 + + Sheet.1011 + 0x2100_0000 + + 0x2100_0000 + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memorymap.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memorymap.png new file mode 100644 index 00000000000..1f5d0edc84a Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_memorymap.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_default_manifest_topology.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_default_manifest_topology.png new file mode 100644 index 00000000000..ffe7f73da25 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_default_manifest_topology.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_dfu_overview.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_dfu_overview.png new file mode 100644 index 00000000000..fa5c7477ece Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_dfu_overview.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_envelope_structure.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_envelope_structure.png new file mode 100644 index 00000000000..18a23494b04 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_envelope_structure.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_package.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_package.png new file mode 100644 index 00000000000..573e4dc18ad Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_package.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_process.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_process.png new file mode 100644 index 00000000000..925594025f9 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_process.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_workflow.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_workflow.png new file mode 100644 index 00000000000..ad6eba9a2a1 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_example_update_workflow.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_generator_workflow.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_generator_workflow.png new file mode 100644 index 00000000000..06f3abe6a12 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_generator_workflow.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_invocation_workflow.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_invocation_workflow.png new file mode 100644 index 00000000000..67178285a6c Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_invocation_workflow.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_manifest_topology.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_manifest_topology.png new file mode 100644 index 00000000000..1059024e5e6 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_manifest_topology.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_mcuboot_comparison.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_mcuboot_comparison.png new file mode 100644 index 00000000000..f89cef11177 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_mcuboot_comparison.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_update_workflow.png b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_update_workflow.png new file mode 100644 index 00000000000..e8822685346 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/nrf54h20_suit_update_workflow.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20.svg new file mode 100644 index 00000000000..6e0f5acbc84 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20.svg @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + Page-1 + + Sheet.1015 + + + + Sheet.661 + + + + Dynamic connector.1022 + + + + Sheet.662 + nRF54H20 Application Core + + nRF54H20 Application Core + + Sheet.663 + Application + + Application + + Sheet.699 + Zephyr integration + + Zephyr integration + + Sheet.701 + Secure boot + + Sheet.702 + + + + Zephyr integration + + + Sheet.1016 + nRF54H20 Radio Core + + nRF54H20 Radio Core + + Sheet.1018 + Multiprotocol Service Layer (MPSL) + + Multiprotocol Service Layer (MPSL) + + Sheet.1023 + OpenAMP (Spinel) + + OpenAMP (Spinel) + + Sheet.1007 + + + + Sheet.1008 + nRF IEEE 802.15.4 radio driver + + nRF IEEE 802.15.4radio driver + + Sheet.1009 + IEEE 802.15.4 PHY + + IEEE 802.15.4 PHY + + Sheet.1072 + + Sheet.667 + + + + Sheet.668 + Thread stack (OpenThread) + + Thread stack (OpenThread) + + + Sheet.1073 + + Sheet.703 + + + + Sheet.704 + nRF IEEE 802.15.4 radio driver + + nRF IEEE 802.15.4 radio driver + + + Sheet.1074 + + + + Sheet.1075 + nRF54H20 Secure Domain + + nRF54H20 Secure Domain + + Sheet.1081 + Cryptographically Secure Pseudo Random Number Generator + + Cryptographically Secure Pseudo Random Number Generator + + Sheet.1082 + Cryptography + + Cryptography + + Sheet.1083 + Key management + + Key management + + Sheet.1084 + + Sheet.1079 + + + + Sheet.1080 + Device Firmware Update + + Device Firmware Update + + + Sheet.1085 + + Sheet.1077 + + + + Sheet.1078 + Secure storage + + Secure storage + + + Dynamic connector.1086 + + + + Dynamic connector.1087 + + + + Dynamic connector.1088 + + + + Dynamic connector.1089 + + + + Dynamic connector.1090 + + + + Sheet.1091 + PSA Crypto API + + PSA Crypto API + + Sheet.1092 + PSA Crypto API + + PSA Crypto API + + Sheet.1093 + Remote Procedure Call + + Remote Procedure Call + + Sheet.1094 + (nRF RPC; between domains) + + (nRF RPC; between domains) + + Sheet.1095 + (Thread security mgmt) + + (Thread security mgmt) + + Sheet.1096 + (Matter security mgmt) + + (Matter security mgmt) + + Sheet.1097 + Remote Procedure Call + + Remote Procedure Call + + Sheet.1098 + (nRF RPC; between domains) + + (nRF RPC; between domains) + + Sheet.1099 + PSA Crypto API + + PSA Crypto API + + Sheet.1100 + (Radio security mgmt) + + (Radio security mgmt) + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20_multi.svg b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20_multi.svg new file mode 100644 index 00000000000..a076c32768a --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/images/thread_platform_design_nRF54h20_multi.svg @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + Page-1 + + Sheet.1015 + + + + Sheet.661 + + + + Sheet.1071 + + Sheet.665 + + + + Sheet.666 + Bluetooth® LE stack + + Bluetooth® LE stack + + + Dynamic connector.1022 + + + + Sheet.662 + nRF54H20 Application Core + + nRF54H20 Application Core + + Sheet.663 + Application + + Application + + Sheet.699 + Zephyr integration + + Zephyr integration + + Sheet.701 + Secure boot + + Sheet.702 + + + + Zephyr integration + + + Sheet.780 + + Sheet.683 + + + + Sheet.764 + Zephyr host + + Zephyr host + + + Sheet.1016 + nRF54H20 Radio Core + + nRF54H20 Radio Core + + Sheet.1018 + Multiprotocol Service Layer (MPSL) + + Multiprotocol Service Layer (MPSL) + + Sheet.1023 + OpenAMP (Spinel) + + OpenAMP (Spinel) + + Dynamic connector.1025 + + + + Sheet.1024 + OpenAMP (HCI) + + OpenAMP (HCI) + + Sheet.1011 + + + + Sheet.1013 + nRF Bluetooth® LE Controller + + nRF Bluetooth® LE Controller + + Sheet.1007 + + + + Sheet.1008 + nRF IEEE 802.15.4 radio driver + + nRF IEEE 802.15.4radio driver + + Sheet.1009 + IEEE 802.15.4 PHY + + IEEE 802.15.4 PHY + + Sheet.1072 + + Sheet.667 + + + + Sheet.668 + Thread stack (OpenThread) + + Thread stack (OpenThread) + + + Sheet.1073 + + Sheet.703 + + + + Sheet.704 + nRF IEEE 802.15.4 radio driver + + nRF IEEE 802.15.4 radio driver + + + Sheet.1074 + + + + Sheet.1075 + nRF54H20 Secure Domain + + nRF54H20 Secure Domain + + Sheet.1081 + Cryptographically Secure Pseudo Random Number Generator + + Cryptographically Secure Pseudo Random Number Generator + + Sheet.1082 + Cryptography + + Cryptography + + Sheet.1083 + Key management + + Key management + + Sheet.1084 + + Sheet.1079 + + + + Sheet.1080 + Device Firmware Update + + Device Firmware Update + + + Sheet.1085 + + Sheet.1077 + + + + Sheet.1078 + Secure storage + + Secure storage + + + Dynamic connector.1086 + + + + Dynamic connector.1087 + + + + Dynamic connector.1088 + + + + Dynamic connector.1089 + + + + Dynamic connector.1090 + + + + Sheet.1091 + PSA Crypto API + + PSA Crypto API + + Sheet.1092 + PSA Crypto API + + PSA Crypto API + + Sheet.1093 + Remote Procedure Call + + Remote Procedure Call + + Sheet.1094 + (nRF RPC; between domains) + + (nRF RPC; between domains) + + Sheet.1095 + (Thread security mgmt) + + (Thread security mgmt) + + Sheet.1096 + (Matter security mgmt) + + (Matter security mgmt) + + Sheet.1097 + Remote Procedure Call + + Remote Procedure Call + + Sheet.1098 + (nRF RPC; between domains) + + (nRF RPC; between domains) + + Sheet.1099 + PSA Crypto API + + PSA Crypto API + + Sheet.1100 + (Radio security mgmt) + + (Radio security mgmt) + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_app_samples.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_app_samples.rst new file mode 100644 index 00000000000..773147437f6 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_app_samples.rst @@ -0,0 +1,38 @@ +:orphan: + +.. _ug_nrf54h20_app_samples: + +nRF54H20 applications and samples +################################# + +.. contents:: + :local: + :depth: 2 + +This page outlines the available samples for the nRF54H20. +It includes the nRF Connect SDK samples and nRF Connect SDK application sections that showcase how to implement typical use cases with Nordic Semiconductor libraries and drivers. +Additionally, the page lists the available Zephyr samples that are compatible with the nRF54H20. +You can also find these in Zephyr's Samples and Demos documentation. + +|NCS| samples +************* + +The following |NCS| samples have been developed and tested on the nRF54H20: + +* :ref:`multicore_hello_world` + +|NCS| applications +****************** + +The following |NCS| application has been developed and tested on the nRF54H20: + +* :ref:`nrf_machine_learning_app` +* :ref:`nrf_desktop` +* ``nrf_tbr_app`` + +Zephyr samples +************** + +The following Zephyr samples have been developed and tested on the nRF54H20: + +* :zephyr:code-sample:`blinky` diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture.rst new file mode 100644 index 00000000000..24db1c8d175 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture.rst @@ -0,0 +1,31 @@ +:orphan: + +.. _ug_nrf54h20_architecture: + +Architecture of nRF54H20 +######################## + +.. contents:: + :local: + :depth: 2 + +The nRF54H20 is a multicore System-on-Chip (SoC) that uses an asymmetric multiprocessing (AMP) configuration. +Each core is tasked with specific responsibilities, and is optimized for different workloads. + +The following documents introduce the architecture of the nRF54H20 SoC: + +* The `Introduction to nRF54H20`_ PDF document, providing an overview of the hardware and software features of the nRF54H20. +* The `nRF54H20 Objective Product Specification 0.3.1`_ (OPS) PDF document. +* The `nRF54H20 prototype difference`_ PDF document, listing the major differences between the final and the prototype silicon provided on the nRF54H20 PDK. + +The following pages briefly describe topics like the responsibilities of the cores, their interprocessor interactions, the memory mapping, and the boot sequence in the nRF54H20 SoC. + +.. toctree:: + :maxdepth: 2 + :caption: Subpages: + + ug_nrf54h20_architecture_cpu + ug_nrf54h20_architecture_memory + ug_nrf54h20_architecture_ipc + ug_nrf54h20_architecture_boot + ug_nrf54h20_architecture_lifecycle diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_boot.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_boot.rst new file mode 100644 index 00000000000..2c554690bd8 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_boot.rst @@ -0,0 +1,87 @@ +:orphan: + +.. _ug_nrf54h20_architecture_boot: + +nRF54H20 Boot Sequence +###################### + +.. contents:: + :local: + :depth: 2 + +The nRF54H20 startup procedure can be performed in two scenarios: + + * Cold boot + * Warm boot + +During cold boot the system has no state retained in its RAM memory or hardware registers and performs full initialization. +This procedure is performed on following events: + + * Power on reset + * Pin reset + * System Controller watchdog reset + * Ctrl-AP reset (debugging Secure Domain or System Controller) + * Secure Domain reset request + * Secure Domain watchdog reset + * Tamper detection + +Warm boot is performed when system is being woken up from a deep sleep (system off with RAM retention). +The state of the system is retained in RAM. +This procedure is faster than cold boot, because content of the memories represents operational state of the system. +The procedure requires only restoring the state of hardware peripherals and registers. +The triggers of the warm boot procedure are: + + * GPIO event + * LPCOMP event + * NFC field detection + * USB VBUS rising + * Entering the debug interface mode + * GRTC event + +Cold Boot Sequence +****************** + +The nRF54H20 boot sequence has two key characteristics: + +* An immutable boot ROM provides the initial root-of-trust (RoT). + This boot ROM is responsible for verifying the secure domain firmware signature before allowing the code to be executed. +* The secure domain acts as the boot master in the system. + It completes the allocation of all the global resources before any other local domain is allowed to execute. + This order of operation is needed for robustness and security of the system. + It ensures that global resources are allocated for other local domains before any of them has opportunity to access global resources (correct access to allocated resources, or tries of malicious access to resources owned by other domains). + +Boot stages +*********** + +The Secure Domain boots the System Controller, the Application Core, and the Radio Core: + +* VPRs (PPR, FLPR, BBPROC) are started by their owners when the owners decide. +* PPR and FLPR are owned by the Application Core in most applications, but any of them can be reassigned to the Radio Core. + +See the following overview of the boot sequence, where the left-most block indicates what starts first from when power-on reset is applied. + +.. figure:: images/nRF54H20_bootsequence.svg + :alt: Boot sequence of the nRF54H20 + + Boot order of the nRF54H20 + +The following is a description of the boot sequence steps: + +1. Immediately after reset, the SysCtrl CPU starts executing code from a ROM memory in Global Domain. + This ROM code perform chip calibration, like trim and power-up the MRAM macro. + This ROM code does not affect the runtime services offered by SysCtrl firmware during the secondary boot stage. + +#. The SysCtrl ROM powers up the secure domain and then halts. + +#. The secure domain is taken out of reset (as the first local domain), and the Cortex-M33 CPU inside the secure domain automatically starts executing code from a local ROM memory. + As the MRAM is now calibrated and working correctly, the secure domain ROM can perform signature verification of the secure domain firmware components installed into the MRAM. + The secure domain ROM also configures the device according to the current life-cycle state (LCS) and extracts silicon-unique fingerprints from the physical unclonable function (PUF) in GD , retaining this inside CRACEN. + +#. If the secure domain firmware signature is valid, the secure domain ROM reconfigures ROM memory as non-executable and non-readable and then branches into the firmware stored in MRAM. + This is the first step of the primary boot stage where a user-installable firmware component is executed by any CPU in the system. + +#. At the end of the primary boot stage, the secure domain firmware configures and restricts access to all global resources, and initiates the secondary boot stage. + +#. In the secondary boot stage, SysCtrl and other local domains are released from reset and in parallel start to execute their respective MRAM firmware components. + +#. Each of the local domains is responsible to configure its local resources partitioning. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_cpu.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_cpu.rst new file mode 100644 index 00000000000..5b3cd84df08 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_cpu.rst @@ -0,0 +1,180 @@ +:orphan: + +.. _ug_nrf54h20_architecture_cpu: + +nRF54H20 Domains +################ + +.. contents:: + :local: + :depth: 2 + +The nRF54H20 is partitioned into functional blocks, called *Domains*. +The domains containing the user-programmable main CPUs and associated functions are called *Cores*. +Most memory and peripherals can be flexibly allocated to cores at compile time. +To make this possible, the memory and peripherals are located in a separate area called the Global Domain. +Security functions are centralized into the Secure Domain. + +The following image shows the domains in the nRF54H20: + +.. figure:: images/nRF54H20_Domains.svg + :alt: nRF54H20 Domains + + nRF54h20 Domains + +The CPU cores in the nRF54H20 are based on two types of CPU architectures: + +* Arm Cortex-M33. +* RISC-V (VPR cores). + The VPR (pronounced “Viper”) is a small, efficient CPU developed by Nordic Semiconductor. + It is compatible with the RISC-V instruction set. + +Application Core +**************** + +The following image shows the Application Core in the final silicon: + +.. figure:: images/nRF54H20_appcore.svg + :alt: Application Core + + Application Core + +The Application Core contains the Arm Cortex-M33 CPU with the highest processing power in the system. +Its purpose is to run the main application. +It is also designed to have the highest active power efficiency, meaning it can run computing-intensive operations at an optimal power consumption. + +Due to Dynamic Voltage and Frequency Scaling (DVFS) support and power efficiency optimizations, it takes some time for it to start and stop. +That is why the workloads that require frequent starting and stopping are better suited to run either on the Radio Core or the PPR and FLPR processors. + +Moreover, the clock speed of the processor is very high compared to the low-leakage peripherals running at 16 MHz. +This means that in a code frequently accessing peripheral registers, the Application Core wastes multiple cycles waiting for the peripherals to respond. +Code requiring a lot of accesses to low-leakage peripherals in the Global Domain is better suited to run on the PPR processor if efficiency is a key concern. + +32 kB of local RAM, which is configured like a Tightly Coupled Memory (TCM) and is accessible single-cycle, is provided. +This can be used by timing-sensitive code that cannot tolerate variable latency due to cache hits/misses when accessing memory. + +.. note:: + During the initial limited sampling, the firmware to change DVFS settings will not be available, and all code will run at the maximum clock frequency. + Dynamic switching of voltage and frequency will be enabled at a later date. + In later versions, developers will be able to select an optimal clock frequency at run time, depending on the task at hand. + +Radio Core +********** + +The following image shows the Radio Core in the final silicon: + +.. figure:: images/nRF54H20_radiocore.svg + :alt: Radio Core + + Radio Core + +The Radio Core is intended to run the radio protocol stacks, such as Bluetooth Low Energy, IEEE 802.15.4, Thread, Enhanced ShockBurst (ESB), or other proprietary protocols. +It is also possible to implement a combination of protocols that use multiprotocol support. + +.. note:: + IEEE 802.15.4 will not be supported for the initial limited sampling. + +Any remaining processing power of this core can be used for tasks other than the ones required by the radio protocol stacks. + +The main CPU in the Radio Domain is an Arm Cortex-M33 running at a fixed clock speed of 256 MHz and is optimized for quick starts and stops, which are frequent in protocol stack workloads. +Other workloads with similar characteristics are also well suited for running on the Radio Core. + +.. note:: + The protocol stack software may need to run at the highest priority to meet its timing requirements. + If that is the case, the user code needs to run at lower priority. + +The Radio Core has 192 kB of local RAM, making single-cycle memory accesses possible. + +.. note:: + In the prototype silicon provided for the initial limited sampling, the size of the local RAM is 64 kB. + +For performance reasons, the Radio Core includes its own AES-128 hardware accelerator for implementing link-layer encryption. +For asymmetric cryptography, it relies on services provided by the Secure Domain. + +The Radio Core is user-programmable, if you want to add or modify code, but it is also possible to leave the core running Nordic’s default protocol stack software and only engage with its high-level interface. +Since the Radio Core is physically separate from the Application Core, a separation of concerns exists, and, unlike single-core implementations, the protocol stack software running on the Radio Core will not influence the execution of application code running on the Application Core. + +While any peripheral in Radio's local APB2 bus (including the radio) is active, the 32 MHz crystal oscillator will be enabled, and the radio itself will be clocked from this clock source. + +Global Domain +************* + +The following image shows the Global Domain in the final silicon: + +.. figure:: images/nRF54H20_globaldomain.svg + :alt: Global Domain + + Global Domain + +The Global Domain contains most of the memory and peripherals of the nRF54H20. +This offers flexibility to assign memory regions and peripherals to different cores. +If this flexibility is not needed, it is possible to use the |NCS| defaults, where most of the memory and peripherals are assigned to the Application Core. + +The Global Domain includes two sets of power domains: + +* The low-leakage power domains runs at a clock speed of 16 MHz and contains the peripherals that do not need a higher clock speed than this. +* The high-speed power domains contains the main memories (MRAM and RAM) and high-speed peripherals that have clock speeds higher than 16 MHz. + +Peripheral Processor (PPR) +========================== + +The Peripheral Processor (PPR, pronounced “Pepper”) is a VPR core running at 16 MHz located in the low-leakage area of the Global Domain. +It is designed to perform simple I/O-related operations and low-level peripheral handling with lower power and lower latency than the Arm-based processors. + +This processor is suitable for the following use cases: + +* Reading and aggregating data from sensors. + Based on data, making decisions on when to wake up the rest of the system. +* Servicing serial ports. +* Coordinating several peripherals to achieve a task. + +It has been optimized for using very few clock cycles to service interrupts and can start and stop quickly. +Since the PPR is running from the same clock as the low-leakage peripherals, it does not need to implement any wait cycles to access peripheral registers. + +Fast Lightweight Processor (FLPR) +================================= + +The Fast Lightweight Processor (FLPR, pronounced Flipper) is a VPR core running at up to 320 MHz, located in the high-speed area of the Global Domain. +This CPU is intended to implement software-defined peripherals. + +.. note:: + FLPR firmware support will not be available during the initial limited sampling. + +Secure Domain +************* + +The Secure Domain (SecDom) is a dedicated domain which executes a pre-compiled and Nordic Semiconductor-signed firmware component. +It exposes security services to the other cores through an IPC interface. + +The Secure Domain has its own CPU, local RAM, and local peripherals to provide background services to the other Cores. +The Secure Domain provides the initial root of trust (RoT), handles all the global resource allocation, acts as a trusted third party (TTP) between other MCU domains, and is used to secure cryptographic operations. +Since the nRF54H platform supports global resource sharing, where memory partitions and peripherals in the global domain can be assigned to different local domains, the Secure Domain Firmware controls this partitioning while also acting as the boot master for the entire system. + +The Secure Domain Firmware (SDFW) exposes security-related services to the Cores in the system located in local domains (like Application and Radio). + +System Controller +***************** + +System Controller is a VPR that implements system startup and power management functionalities that in the past would have been implemented in hardware. + +Cores management +**************** + +In the nRF54H20, the cores can be divided into the following groups: cores that are programmable by the user, by Nordic, or by both. + +Cores managed by Nordic Semiconductor + Secure Domain and System Controller are cores that are exclusively managed by Nordic Semiconductor. + + The firmware for cores managed by Nordic will come as part of the nRF Connect SDK. + This means that the components can be modified by Nordic Semiconductor only. + +Cores managed by the user and Nordic Semiconductor + Firmware for the Radio Core will come as part of the nRF Connect SDK. + You can either use the default Nordic’s Radio Core firmware, modify it, or provide a custom implementation. + If you rely on Nordic to provide the firmware, the default correct controller library will be used depending on the short-range protocol selected in the software configuration. + +Cores managed by the user + Although there are multiple distinctive cores in the system, you will be responsible mostly for preparing the firmware for the Application Core. + If the application firmware is executed in non-secure mode, the secure firmware (TF-M) is delivered as part of the nRF Connect SDK. + + You can choose to move some of the processing from the Application Core to the Peripheral Processor (PPR) or to the Fast Lightweight Processor (FLPR). diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_ipc.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_ipc.rst new file mode 100644 index 00000000000..ae84f73cc0f --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_ipc.rst @@ -0,0 +1,224 @@ +:orphan: + +.. _ug_nrf54h20_architecture_ipc: + +Interprocessor Communication in nRF54H20 +######################################## + +.. contents:: + :local: + :depth: 2 + +Interprocessor communication (IPC) is the communication between different CPUs (and domains). +The nRF54H20 includes several types of CPUs that are optimized for different types of workloads. +This provides an asymmetric multiprocessing environment where you can freely select the CPU that is best suited to the workloads that compose your application. + +Interprocessor Communication is required in asymmetric multiprocessing environments to share services' requests, responses, and data between processors. + +The following sections describe the communication protocol used for IPC in |NCS| for the nRF54H20 SoC. +They also include an overview of the connection scheme between the cores available in the system. + +Technical solution +****************** + +A single Interprocessor Communication instance used in the nRF54H20 SoC allows full-duplex communication between two cores. +It support only unicast messages. + +To communicate with multiple peers, a core requires multiple IPC instances, at least as many as the number of peers. +It is possible to create multiple IPC instances towards a single peer to separate messages with different priority levels. +The number of IPC instances which might be created is limited by the available hardware resources (numbers of channels in the signaling peripherals). + +The Interprocessor Communication can be described using the OSI model. +See the following figure: + +.. figure:: images/nrf54h20_IPC_layers.svg + :alt: nRF54H20 IPC layers + +Physical layer +============== + +The physical layer used by IPC in the nRF54H20 SoC consists of shared RAM and signaling peripherals. + +The shared RAM must be accessible (both for reads and writes) by both cores using this RAM region for communication. +See :ref:`General-purpose shared RAM (RAM0x)` for a description of shared RAM and its placement in the memory map. + +Signaling peripherals are the hardware peripherals which can be used by one core to trigger an IRQ in another core. +Each ARM Cortex-M33 core in nRF54H20 has an associated BELLBOARD signaling peripheral. +Each VPR core in nRF54H20 has an associated VEVIF signaling peripheral: + +* When a core signals an IRQ to its ARM Cortex-M33 peer, it uses the BELLBOARD associated with the peer. +* When a core signals an IRQ to a VPR peer, it uses the VEVIF associated with the peer. +* When a core receives an IRQ signal, it uses the BELLBOARD or the VEVIF associated with it, regardless which peer originated the signal. + +Each VEVIF and BELLBOARD has multiple channels. +The peer originating the signal is recognized with a channel number associated with the peer. +The channel numbers association is presented in the following table: + +============================ ========== +Signal originator Channel id +============================ ========== +SecDom 0 +SecDom: signal to a debugger 1 +System Controller 6 +Application 12 +Radio 18 +============================ ========== + +Some of the channels in BELLBOARDs and VEVIFs are interpreted differently by other receivers. + +The following tables show signals received only by specified cores. + + Secure Domain core: + + ============================ ========== + Signal originator Channel id + ============================ ========== + System Controller's debugger 7 + Application's debugger 13 + Radio's debugger 19 + ============================ ========== + + Application core: + + This assignment applies only when PPR and FLPR owner is set to the Application. + + ================= ========== + Signal originator Channel id + ================= ========== + PPR 12 + FLPR 13 + ================= ========== + + Radio Core: + + This assignment applies only when BBPROC owner is set to the Radio. + + ================= ========== + Signal originator Channel id + ================= ========== + BBPROC 18 + ================= ========== + +Some of the channels in BELLBOARDs and VEVIFs are reserved for functions different from IPC. + +MAC, Network, Transport +======================= + +The layers responsible for maintaining a stable full-duplex stream of data between two cores (MAC, Network, Transport) are implemented in an IPC transport library. +The default IPC transport library for nRF54H20 is :ref:`ICMsg `. +This lightweight library maintains the connection between a pair of cores for each IPC instance with minimal memory overhead. +Each IPC instance requires an instance of the icmsg library. +Each icmsg library instance requires the following: + + * One memory buffer for A->B messages + * One memory buffer for B->A messages + * A pair of signaling channels (one for A->B, one for B->A). + +The icmsg library is designed to efficiently send short messages to a peer. +Its buffer allocation is not optimized for bulk transfer of long messages and it does not provide a zero-copy model. +To transfer bigger amount of data (like network packets) between two cores, icmsg can be used as control plane. +However, you must use as data plane memory allocation mechanisms optimized for bigger data and supporting flexible memory allocation and a zero-copy model (like Zephyr's :ref:`zephyr:net_buf_interface`). + +.. note:: + The memory allocation mechanism for the data plane is a single-core memory allocation working on shared memory buffers. + It does not have to involve another IPC transport. + The ownership of the shared buffers is passed between the cores using the control plane, but only one of the cores is responsible for managing (allocating, resizing, freeing) the buffers. + +For more information, consult the :ref:`ICMsg ` backend documentation. + +Session +======= + +The IPC session establishment in the nRF54H20 SoC is performed by the :ref:`IPC service ` library. +This library provides a unified API for IPC transports and it integrates specific transports as its backends. +ICMsg is integrated as one of the available IPC service backends. +The library is responsible for creating IPC instances based on the system configuration described in the devicetree. + +It is recommended to use the ipc_service API to perform inter-processor communication in the nRF54H20 SoC. + +For more information, consult the :ref:`IPC service ` library documentation. + +Presentation and Application layers +=================================== + +The presentation and application layers are connection specific. +Each connection has other requirements regarding the type and the nature of the exchanged messages. + +The solutions selected for each connection are listed in the table below: + +====================== ===================== +Connection Communication library +====================== ===================== +System Controller nrfs +Secure Domain RPC (:ref:`nrfxlib:nrf_rpc`) +Radio Bluetooth HCI or :ref:`nrfxlib:nrf_rpc` +Radio 802.15.4 Spinel +PPR with event_manager :ref:`event_manager_proxy` +====================== ===================== + +IPC connections scheme +********************** + +The following figures show the IPC connection schemes in the nRF54H20 SoC: + +.. figure:: images/nrf54h20_cpu_to_cpu.svg + :alt: nRF54H20 IPC between ARM cores + +.. figure:: images/nrf54h20_arm_to_vpr.svg + :alt: nRF54H20 IPC between ARM cores and VPR cores + +Radio core +========== + +The Radio core exposes radio communication services to the Application Core through IPC. +These services include: + + * Bluetooth (HCI or host API) + * IEEE 802.15.4 radio driver API + +These services are hidden behind Zephyr APIs available in the Application Core, like the Bluetooth host API or the IEEE 802.15.4 driver API. +All services can be enabled simultaneously using separated endpoints in a shared IPC instance. +You can implement other services running in the Radio Core and expose them to the Application Core using more endpoints from the shared IPC instance. + +Secure Domain core +================== + +The Secure Domain core exposes security-related services to the other local cores in the system (Application, Radio). +The list of services also includes: + + * Key management + * Secure storage + * Cryptography + + * Cryptographically Secure Pseudo Random Number Generator + + * Device Firmware Upgrade + * Debugger access management + * Reset notifications + * Encrypted core dumps + +System Controller +================= + +The System Controller exposes the following services to local cores (Application, Radio, Secure Domain) through IPC: + + * Clocks accuracy notification and calibration requests + * MRAM latency management (related to power management) + * CPU frequency management (using Dynamic Voltage and Frequency Scaling) + * Die temperature service + * L2CACHE performance + * Power output service + +Fast Lightweight Processor (FLPR) +================================= + +The Fast Lightweight Processor (FLPR) exposes IPC communication for its owner to manage its operations. +The communication details depends on the FLPR role in the system. + +Peripheral Processor (PPR) +========================== + +The Peripheral Processor (PPR) exposes IPC communication for its owner to manage its operations. +The communication details depends on the PPR role in the system. + +In the :ref:`nrf_machine_learning_app` application, PPR uses an :ref:`event_manager_proxy` through IPC to extend the Event Manager framework running in the Application Core. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_lifecycle.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_lifecycle.rst new file mode 100644 index 00000000000..9a044ec192d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_lifecycle.rst @@ -0,0 +1,58 @@ +:orphan: + +.. _ug_nrf54h20_architecture_lifecycle: + +nRF54H20 lifecycle states +######################### + +.. contents:: + :local: + :depth: 2 + +The Secure Domain ROM firmware defines the lifecycle states (LCS) for the nRF54H20 SoC. +The states are based on the Arm PSA Security Model and allow for programming and safely erasing the device assets. + +.. caution:: + The device must be kept to Root of Trust (RoT) during the initial limited sampling. + Changing the lifecycle state of the nRF54H20 devices during the initial limited sampling will brick your devices. + + The lifecycle state will be changeable only in the final silicon. + +The LCS available are the following: + +.. list-table:: nRF54H20 lifecycle states + :header-rows: 1 + :align: center + :widths: auto + + * - LCS + - Supply chain stage + - Description + * - EMPTY + - Production + - RAM empty and Secure Domain Firmware unprogrammed. + * - Root of Trust + - Production + - Secure Domain Firmware and certificates provisioned. + * - DEPLOYED + - In-field + - Secure Domain debug access port is locked, and unlock is only possible using an authenticated operation. + * - ANALYSIS + - End-of-life + - All device assets in MRAM are erased to allow for Nordic RMA procedures. + * - DISCARDED + - End-of-life + - All device assets in MRAM are erased. + +See the following diagram: + +.. figure:: images/nRF54H20_lifecycle_states.svg + :alt: nRF54H20 lifecycle states and transitions + + nRF54H20 lifecycle states and transitions available on the final silicon. + +This figure shows the states and transitions that will be available on the final silicon. +Black arrows illustrate forward unauthenticated transitions and red arrows illustrate backward authenticated transitions. + +Changing the lifecycle state will be useful during development. +Test devices in their final configuration would require the device to be in the deployed state, however, updating the Secure Domain firmware and the System Controller firmware will be easier with the device in RoT state. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_memory.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_memory.rst new file mode 100644 index 00000000000..022c54f2d6b --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_architecture_memory.rst @@ -0,0 +1,453 @@ +:orphan: + +.. _ug_nrf54h20_architecture_memory: + +nRF54H20 Memory Layout +###################### + +.. contents:: + :local: + :depth: 2 + +The memory inside the nRF54H20 can be classified by several characteristics, like retention without power and CPU association. +When classifying memories by storage time, the nRF54H20 contains the following types of memory: + +* Static RAM (RAM) +* Magnetic RAM (MRAM) with non volatile memory properties + +MRAM retains its content after disconnecting the system from power, while RAM does not. +MRAM is intended to store executable firmware images, as well as credentials, and other data at rest. + +When classifying memories by a CPU association, the nRF54H20 contains the following types of memory: + +* Local Memory +* Global Memory + +The MRAM is a global memory available to all CPUs in the system. +Some RAM memories are, instead, tightly coupled to a specific CPU, while others are intended to be shared between multiple CPUs. + +.. note:: + In the nRF54H20 initial limited sampling, TrustZone is disabled on all cores. + +RAM +*** + +There are multiple RAM banks in the system. +Each local domain (like Application or Radio) contains its own RAM. +There is also a large part of the RAM in the global domain to be shared between the cores in the system. + + +.. image:: images/nrf54h20_memorymap.png + +Local RAM +========= + +Local RAM is present in each of local domains + +Application Core RAM +-------------------- + +.. image:: images/nrf54h20_memory_map_app.svg + :width: 300 px + +The Application Core contains 32 KB of local RAM. +Accessing this memory from the Application Core CPU has minimal latency, but accessing it from any other core adds significant latency. +Because of this property, the local RAM in the application domain should be used mainly to store data frequently accessed by the Application Core, or to store timing-critical parts of the code executed by Application Core. + +Address range + 0x22000000 - 0x22008000 + +Size + 32 KB + +Access control + Application domain local RAM is accessible by the Application Core. + Any core (like FLPR or PPR) or peripheral configured to be owned by Application Core (like UARTE or SAADC) can access this memory as well. + Any core with access to this memory can execute code from it. + + If the TrustZone feature is enabled for Application Core, this memory can be partitioned in one secure and one non-secure region. + The secure region is accessible only by code executed with the secure attribute, while the non-secure region is accessible by any code. + + .. note:: + Code executed by VPRs (like FLPR or PPR) has its secure attribute matching the given VPR security configuration in the SPU. + Local RAM cannot include a Non-Secure Callable section. + +Radio Core RAM +-------------- + +.. image:: images/nrf54h20_memory_map_radio.svg + :width: 300 px + +The Radio Core contains 96 KB of local RAM. +Any access to this memory has minimal latency if originated either from Radio Core CPU or from peripherals with EasyDMA located in the Radio Core. +Any access from any other core has a significant latency. +Because of this property, local RAM in the Radio Core should be used mainly to store data frequently accessed by the Radio Core CPU or the radio protocol frames to be accessed by CCM or RADIO peripherals, or to store timing critical parts of the code executed by the Radio Core CPU. + +Address range + 0x23000000 - 0x23018000 + +Size + 96 KB + +Access control + The Radio Core local RAM is accessible by the Radio Core. + Any core (like FLPR or PPR) or peripheral configured to be owned by the Radio Core (like UARTE or SAADC) can access this memory as well. + Any core with access to this memory can execute code from it. + + If the TrustZone feature is enabled for the Radio Core, this memory can be partitioned in one secure and one non-secure region. + The secure region is accessible only by code executed with the secure attribute, while the non-secure region is accessible by any code. + + .. note:: + Code executed by VPRs (like FLPR or PPR) has its secure attribute matching the given VPR security configuration in the SPU + Local RAM cannot include a Non-Secure Callable section. + +BBPROC memory +^^^^^^^^^^^^^ + +.. image:: images/nrf54h20_memory_map_bbproc.svg + :width: 300 px + +The Lower 32 KB of local RAM in the Radio Domain (0x23010000 - 0x23018000) is tightly coupled with BBPROC. +Any access to this memory has minimal latency if originated from BBPROC. +Any access originated from the Radio Core or from peripherals with EasyDMA located in radio domain have a little greater latency while accessing BBPROC memory. +Access from other domains is possible, but with significant latency. + +BBPROC memory is the only memory from which BBPROC can fetch its instructions. +Because of this property, this memory block is mostly intended to store BBPROC code and data. +When BBPROC is unused in a system, this memory can be used as additional local RAM in the Radio Domain. + +Address range + 0x23010000 - 0x23018000 + +Size + 32 KB + +Access control + The access to the BBPROC memory is configured as the access to the local RAM in the Radio Domain. + +Secure Domain +------------- + +.. image:: images/nrf54h20_memory_map_secure.svg + :width: 300 px + +The Secure Domain contains 32 KB of local RAM. +Any access to this memory from the Secure Domain core has minimal latency, but accesses from any other core have significant latency. +Because of this property, the local RAM in the Secure Domain should be used mainly to store data frequently accessed by its local core, or to store timing critical parts of the code executed by it. + +Address range + 0x21000000 - 0x21008000 + +Size + 32 KB + +Access control + The Secure-Domain local RAM is accessible by its local core. + Any core (like FLPR or PPR) or peripheral configured to be owned by the Secure Domain (like UARTE or SAADC) can access this memory as well. + Any core with access to this memory can execute code from it. + + If the TrustZone feature is enabled for the Secure Domain, this memory can be partitioned in one secure and one non-secure region (both regions owned by Secure Domain). + The secure region is accessible only by code executed with the Secure attribute, while the Non-secure region is accessible by any code. + The Local RAM cannot include a Non-Secure Callable section. + +Global RAM +========== + +The Global Domain RAM (or Global RAM, GRAM) is distributed in multiple instances across the system. +Each of the instances has other properties and other purposes. + +.. _ug_nrf54h20_architecture_memory_gp_shared_ram: + +General-purpose shared RAM (RAM0x) +---------------------------------- + +.. image:: images/nrf54h20_memory_map_ram0x.svg + :width: 300 px + +The biggest part of the RAM memory in the system is located in the Global Domain as general-purpose shared RAM. +Access to this memory is relatively fast from all the local domains (like the Application or the Radio ones). +Access to this memory from DMA used by USB has minimal latency. + +This memory is intended to store the majority of the data used by local cores (and does not fit in local domains' RAM) including shared memory used for Inter-Processor Communication (IPC) between local cores. +Buffers for USB data must be stored in this memory part, in the region owned by the core owning USB (usually the Application Core in typical applications). + +Address range + 0x2F000000 - 0x2F0E0000 + +Size + 896 KB + +Access control + The general-purpose shared RAM is split into multiple partitions. + Each of the local cores has two partitions assigned: one configured as Secure, the other one as Non-Secure. + The partitions are configured in the given core's UICR. + + If TrustZone is enabled for a core, the Secure partition is used to store the data of the Secure Processing Environment, while the Non-Secure partition stores the data of the Non-Secure Processing Environment and the shared memory used by the Inter-Processor Communication towards other local domains. + If TrustZone is disabled for a core, the Secure partition assigned to this core is used to store program data, while the Non-Secure partition contains the shared memory used by IPC. + + Secure partitions are grouped at the beginning of the general-purpose shared RAM block, while Non-Secure partitions are grouped at the end. + Non-Secure partitions are overlapping to define shared-memory IPC regions. + + A partition assigned to a core is accessible from this core, other cores owned by this core, or DMAs used by peripherals used by this core. + Access from other cores or peripherals is prevented. + A partition configured as Secure is accessible only from the Secure Processing Environment in the core owning the given partition. + A partition configured as Non-Secure is accessible from both the Secure and Non-Secure Processing Environments running in the core owning the given partition. + + + .. note:: + If TrustZone is disabled for a given core, the only available Processing Environment is Secure. + +SYSCTRL memory (RAM20) +---------------------- + +.. image:: images/nrf54h20_memory_map_ram20.svg + :width: 300 px + +The SYSCTRL memory is a part of the global RAM tightly coupled with the System Controller. +Access to this memory block from the System Controller has minimal latency and can be performed without powering up any other parts of the system. +Access to this memory from the local domains has higher latency than access to the general-purpose shared RAM. + +This memory is statically partitioned. +The layout is not to be adjusted for specific products. + +This memory is intended to store the code executed in the System Controller, the System Controller's data, and the shared memory used for Inter-Processor Communication between the System Controller and other cores. +Because of the static allocation property, this memory stores also the shared memory used for communication between debugger probes connected to cores in the system and the Secure Domain Core. + +Address range + 0x2F880000 - 0x2F890000 + +Size + 64 KB + +Access control + The SYSCTRL memory is split into multiple partitions. + The System Controller has access to all of them (System Controller's code and data, and shared memory regions). + The shared memory regions are also accessible by the cores using particular region for communication with the System Controller and the debugger. + The shared memory regions are configured in the given core's UICR. + Cores do not have access to other parts of the SYSCTRL memory. + + If TrustZone is enabled for a core, the shared memory region is accessible from the Non-Secure Processing Environment. + If TrustZone is disabled for a core, the shared memory region is accessible from the Secure Processing Environment. + +Fast global RAM (RAM21) +----------------------- + +.. image:: images/nrf54h20_memory_map_ram21.svg + :width: 300 px + +The Fast global RAM is a part of the global RAM tightly coupled with the Fast Lightweight Processor. +Access to this memory block from the FLPR and fast peripherals' DMA (I3C, CAN, PWM120, UARTE120, SPIS120, SPIM120, SPIM121) has minimal latency and can be performed without powering up any other parts of the system. +Access to this memory from the local domains has higher latency than access to the general-purpose shared RAM. + +This memory is intended to store the code executed in the FLPR, the FLPR's data, the shared memory used for Inter-Processor Communication between the FLPR and the core managing the FLPR, and DMA buffers for the fast peripherals. + +Address range + 0x2F890000 - 0x2F898000 + +Size + 32 KB + +Access control + The FLPR and its owner have access to all partitions assigned to FLPR and its Inter-Processor Communication. + Each of the memory partition assigned for DMA of the fast peripherals is accessible from the core owning given set of the peripherals. + The FLPR and the fast peripherals are by default owned by the Application Core. + This ownership and matching memory access rights can be customized in UICRs. + + The security attribute of memory partitions must follow FLPR and DMA engines security settings. + +Slow global RAM (RAM3x) +----------------------- + +.. image:: images/nrf54h20_memory_map_ram3x.svg + :width: 300 px + +The Slow global RAM is a part of the global RAM tightly coupled with the Peripheral Processor. +Access to this memory block from the PPR and slow periperals' DMA has minimal latency and can be performed without powering up any other parts of the system. +Access to this memory from the local domains has higher latency than access to the general-purpose shared RAM. + +This memory is intended to store the code executed in the PPR, the PPR's data, the shared memory used for Inter-Processor Communication between the PPR and the core managing the PPR, and DMA buffers for the slow peripherals. + +Address range + 0x2FC00000 - 0x2FC08000 + +Size + 32 KB + +Access control + The PPR and its owner have access to all the partitions assigned to the PPR and its Inter-Processor Communication. + Each of the memory partition assigned for DMA of the slow peripherals is accessible from the core owning the given set of peripherals. + The PPR and the slow peripherals are by default owned by the Application Core. + The ownership and matching memory access rights can be customized in UICRs. + + The security attribute of memory partitions must follow PPR and CMA engines security settings. + +MRAM (non-volatile memory) +************************** + +The MRAM is divided in the following parts: + +* MRAM_10 +* MRAM_11 + +MRAM_10 +======= + +.. image:: images/nrf54h20_memory_map_mram10.svg + :width: 300 px + +The MRAM_10 is a part of the non-volatile memory intended to keep firmware images to execute. +Access to this memory has minimal latency to avoid CPU stalls on instruction fetches. +This part of the memory is not writable while the main application is running (it is writable only during the Firmware Upgrade procedure) to avoid any latency caused by write operations. +Apart from executable code images, this part of the memory stores the Secure Information Configuration Registers (SICR) used by the programs running in the Secure Domain Core. +If code and data for the Application Core do not fit in MRAM_10, it can be partially or fully placed in MRAM_11. + +Address range + 0x0E000000 - 0x0E100000 + +Size + 1024 KB + +Access control + The Application Core and the Radio Core have read and execute access to memory regions assigned to them. + If Trustzone is disabled for any of these cores, then the assigned memory region is a single block containing secure code and data. + If Trustzone is enabled for any of these cores, then the assigned memory region is split in three blocks: + + * Secure code and data + * Non-secure code and data + * Non-secure callable (NSC) + + The code executed in the Secure Processing Environment of a core has access to all three blocks assigned to the core. + The code executed in the Non-Secure Processing Environment has access only to the Non-secure code and data block, and can call function veneers located in the NSC block. + + The System Controller's code and data region is accessible only by the Secure Domain Core. + The content of this region is copied by the Secure Domain Core to RAM_20 before the System Controller is started. + The System Controller accesses its code and data from the copy in RAM_20. + + Secure Domain has access to all parts of the MRAM_10. + Other cores can access only the parts assigned to them, according to the security rules described above. + +MRAM_11 +======= + +.. image:: images/nrf54h20_memory_map_mram11.svg + :width: 300 px + +The MRAM_11 is a part of the non-volatile memory intended to keep non-volatile writable data. +Writing to MRAM_11 can increase access latency for other cores reading from MRAM_11. +When a core is reading or executing code from MRAM_11, the impact of the additional latency must be taken in consideration. +Each of the local cores (Application, Radio, Secure Domain) have an allocated partition in MRAM_11 to store their non-volatile data. +Each of the cores has full control on the data layout and management in the assigned MRAM partition. +There is also a Device Firmware Upgrade partition used to store firmware images used during the upgrade procedure. +If code and data for the Application Core do not fit in MRAM_10, it can be partially or fully placed in MRAM_11. + +Address range + 0x0E100000 - 0x0E200000 + +Size + 1024 KB + +Access control + The Application Core and the Radio Core have read and write access to their assigned non-volatile data regions. + The non-volatile data region assigned to the core having trustzone disabled is marked as Secure, while the non-volatile data region assigned to the core having trustzone enabled is marked as Non-Secure. + + If code or data for the Application Core is placed in MRAM_11, the Application Core has *read and execute* access to this partition. + This access can be configured as follows: + + * Default configuration - all the application code and data is placed in MRAM_10. + It is configured with a single MPC configuration entry contained entirely in MRAM_10. + * All the app code and data is placed in MRAM_11. + It is configured with a single MPC configuration entry contained entirely in MRAM_11. + * The app code and data is partially in MRAM_10, partially in MRAM_11. + It is configured with a single MPC configuration entry covering partially MRAM_10 and partially MRAM_11. + Because of the continuous memory address range it is possible to use a single memory region to describe such data block. + + The Secure Domain has access to all the parts of MRAM_11. + The Application Core has read and write access to the DFU partition. + The security configuration of this partition follows the Trustzone configuration of the Application Core (Secure if Trustzone is disabled, or Non-Secure if Trustzone is enabled). + +Memory Privilege Controller (MPC) configuration +*********************************************** + +The Secure Domain configures Memory Privilege Controllers (MPCs) before it boots other domains. +MPC configuration provides rights for other cores to access memory regions assigned to them. +If a core tries to access a memory address not assigned to it, the transaction fails. + +The Secure Domain can access all the memory regions in the system and does not require explicit access rights in MPC. + +The Secure Domain configures OVERRIDEs in the MPC assigned to ``AXI_0`` to provide the access rights needed: + +=========== ===== =========== ========== ====================================================== +OVERRIDE Id Owner Permissions SECUREMASK Regions +=========== ===== =========== ========== ====================================================== +1 App RW 1 App's NV storage; DFU storage bank +2 Radio RW 1 Radio's NV storage +3 All R any UICRs, FICR +4 App RW 1 Radio <-> App IPC; App's Non-Secure data +5 App RWS 1 * SecDom <-> App IPC; App's Secure data +6 App RX 1 App's Non-Secure code +7 App RXS 0 App's S-NSC; App's Secure code +8 Radio RW 1 Radio <-> App IPC; Radio's Non-Secure data +9 Radio RWS 1 * SecDom <-> Radio IPC; Radio's Secure data +10 Radio RX 1 Radio's Non-Secure code +11 Radio RXS 0 Radio's S-NSC; Radio's Secure code +=========== ===== =========== ========== ====================================================== + +.. note:: + SECUREMASK can be set to ``0`` for any secure memory partition. + However, because of the hardware configuration, OVERRIDEs marked with ``*`` have SECUREMASK set to ``1``. + Such configuration implies that addresses of this entry should have 28th bit cleared. + It does not expose any security thread because permissions filtering denies access from non-secure masters. + +The Secure Domain configures OVERRIDEs in the MPC assigned to ``AXI_1`` to provide the access rights needed: + +=========== ======= =========== ========== ================================================================================================================ +OVERRIDE Id Owner Permissions SECUREMASK Regions +=========== ======= =========== ========== ================================================================================================================ +5 SysCtrl RW 1 Radio's non-volatile storage; App's non-volatile storage; DFU storage bank; Secure Domain's non-volatile storage +=========== ======= =========== ========== ================================================================================================================ + + .. note:: + During the installation step of the Device Firmware Update procedure, write access is enabled for more MRAM partitions. + During this step the only active core is the Secure Domain Core. + +The Secure Domain configures OVERRIDEs in the MPC assigned to ``AXI_2`` to provide the access rights needed: + +=========== ===== =========== ========== ============================================================================== +OVERRIDE Id Owner Permissions SECUREMASK Regions +=========== ===== =========== ========== ============================================================================== +1 App RW 1 Application mngMbox; SysCtrl <-> App IPC +2 App RWX 1 FLPR code; FLPR data; FLPR <-> App IPC; DMA buffers for App's fast peripherals +3 Radio RW 1 Radio mngMbox; SysCtrl <-> Radio IPC +4 Radio RW 1 DMA buffers for Radio's fast peripherals (if any) +=========== ===== =========== ========== ============================================================================== + +The Secure Domain configures OVERRIDEs in the MPC assigned to ``AXI_3`` to provide the access rights needed: + +=========== ===== =========== ========== =========================================================================== +OVERRIDE Id Owner Permissions SECUREMASK Regions +=========== ===== =========== ========== =========================================================================== +1 App RWX 1 PPR code; PPR data; PPR <-> App IPC; DMA buffers for App's fast peripherals +3 Radio RW 1 DMA buffers for Radio's fast peripherals (if any) +=========== ===== =========== ========== =========================================================================== + +SAU configuration +***************** + +.. note:: + In the nRF54H20 initial limited sampling, SAU is disabled and the entire memory is marked as secure. + +Each one of the Cortex-M33 CPUs in the system with the TrustZone feature enabled (specifically, the Application, Radio, and Secure Domain Cores) associates a Security Attribution Unit (SAU) peripheral. +The Secure Domain configures the SAUs for itself during its initialization before it switches to the Non-Secure Processing Environment (NSPE). +The Secure Domain configures the SAUs for other cores before it boots them. + +SAU configuration provides the rights for the Non-Secure Processing Environment to access resources allocated for it. +If the NSPE tries to access a memory address not allocated to it, the transaction fails. + +============= ================== =================================== ==================================================================================================================================================================================== +SAU region Id Security attribute Region Comments +============= ================== =================================== ==================================================================================================================================================================================== +0 NS 0x0000_0000 - 0x1000_0000 The entire non-secure address space of the MRAM. Proper partitioning is done in MPC. +1 NS Core's S-NSC in MRAM S-NSC veneers in the secure address space of MRAM. +2 NS 0x2000_0000 - 0x3000_0000 The entire non-secure address space of the RAM. Proper partitioning is done in MPC. +3 NS Core's S-NSC in RAM - 0x1_0000_0000 S-NSC veneers in the secure address space of the global MRAM, all peripherals, external memory, and CPU registers. If no S-NSC is in the RAM, the start address must be 0x4000_0000. +============= ================== =================================== ==================================================================================================================================================================================== diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_configuration.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_configuration.rst new file mode 100644 index 00000000000..3a992aefc00 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_configuration.rst @@ -0,0 +1,88 @@ +:orphan: + +.. _ug_nrf54h20_configuration: + +Configuring the nRF54H20 DK +########################### + +.. contents:: + :local: + :depth: 2 + +The nRF54H20 DK uses both devicetree and Kconfig for its hardware and software configuration. + +You can find the basics of both devicetree and Kconfig in Zephyr in the :ref:`zephyr:application` section of the Zephyr documentation. +You can also read the :ref:`app_build_system` section describing the |NCS| additions to the Zephyr configuration system. + +However, the multicore nature of the nRF54H20 DK required some changes to the way devicetree files are organized. + +DTS file scheme +*************** + +.. note:: + This file scheme is valid only for the nRF54H20 initial limited sampling version of |NCS|. + It is subject to changes or improvements in future releases. + +The following is the DTS file structure implemented for all the SoCs of the 54H family: + +* Arch-specific DTS files, located in the :file:`../dts/arm/nordic_nrf_next/` and :file:`dts/riscv/nordic_nrf_next folder​` directories: + + * Project-wide files (:file:`haltium_cpu.dtsi` and :file:`haltium_global_*.dtsi`)​ + * Core-specific files per product (:file:`nrf54h20_cpu*.dtsi`)​ + +* Common directory, located in the :file:`../common/nordic_nrf_next` folder​: + + * Arch-independent configurations​ + * Common platform overlays + * Common memory and peripherals overlay applicable across products​ + * Product-specific overlays applicable to all cores​ + * Project-wide overlays + +The following is the include tree for the Application core of the nRF54H20 (cpuapp): + +.. figure:: images/cpuapp_include_tree.svg + :alt: nRF54H20 CPUAPP include tree + +The files shown in the figure are currently hosted in the ``ic-next`` repository. + +Customizing the DTS configuration +********************************* + +The output files created in your application build directory are documented in :ref:`zephyr:devicetree-in-out-files`. +You can use overlay files to customize this configuration. + +To see and test how to use overlays for changing nodes, see the *Lesson 3* of the `nRF Connect SDK Fundamentals course`_ on the Nordic Developer Academy website. + +Generated HEX files +******************* + +When building an application for the nRF54H20 DK, you are building all domain images at once. +During this process, the following :file:`zephyr.hex` images are built: + +* Application core application +* PPR core application +* Secure Domain firmware +* System Controller firmware +* Radio core firmware + +Additionally, the following user information configuration registers (UICR) contents (:file:`uicr.hex`) are generated for setup access for domains: + +* System Controller UICR +* Application UICR +* Radio UICR + +.. note:: + ``west flash`` uses :file:`uicr_merged.hex` files that are pre-merged HEX files combining the relevant :file:`zephyr.hex` + :file:`uicr.hex` for a domain that has UICRs. + Flashing both :file:`zephyr.hex` + :file:`uicr.hex` will result in the same configuration. + +All of the HEX files need to be flashed into the device. +For more information on building images for the nRF54H20 DK, see :ref:`ug_nrf54h20_gs`. +For additional information on multi-image builds see :ref:`ug_multi_image`. + +Other revelant resources +************************ + +For more resources, see the following: + +* The `nrf-regtool`_ - A script tool that generates files of register content for memory-mapped peripherals in Nordic Semiconductor products. +* ``Arborist`` - A framework for validating resources reserved through User Information Configuration Register (UICR) configurations. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_custom_pcb.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_custom_pcb.rst new file mode 100644 index 00000000000..a3770f0227e --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_custom_pcb.rst @@ -0,0 +1,201 @@ +:orphan: + +.. _ug_nrf54h20_custom_pcb: + +Configuring your application for a custom PCB +############################################# + +.. contents:: + :local: + :depth: 2 + +This guide demonstrates how to create your custom board files for your PCB for the nRF54H20 SoC. + +Prepare your PCB +**************** + +First, you need to create your PCB for the nRF54H20 SoC. + +We highly recommend using the PCB layouts and component values provided by Nordic Semiconductor, especially for clock and power sources. +However, if you plan to select your own power sources, consider the following limitations: + +* The DC/DC inductor must be present on the PCB. + If the DC/DC power converter is to be used, the BICR value ``POWER.CONFIG.INDUCTOR`` must also be programmed to ``Present`` (``0``). + + .. note:: + Currently, there is a bug (LIL-9968) causing the nRF54H20 limited sampling SoC to not wake up from the System OFF if DC/DC is enabled. + Temporarily, the workaround is to not use the DC/DC power converter. + +* For the lowest sleep power consumption, use a 32 KHz crystal. +* The **P9** port (3 V) cannot be used with internal nor external pull-down resistors. +* For optimal performance, the output impedance of the **P6** and **P7** ports configured in ``IOPORT.DRIVECTRLX.PY`` should match the PCB and external device pin impedance. + However, an existing limitation requires this configuration to be 50 ohms. + +.. note:: + For a list of major differences between the final and the prototype silicon provided in the initial limited sampling, consult the `nRF54H20 prototype difference`_ document. + +Consult the `nRF54H20 Objective Product Specification 0.3.1`_ (OPS) for more information on the mechanical specification of the SoC package and the reference circuitry used in the PDK. + +Prepare the configuration files for your custom board in the |NCS| +****************************************************************** + +The nRF54H20 PDK uses multiple board files for its configuration: + +* `ARM cores configuration files`_ +* `Risc-V cores configuration files`_ + +You can use these files as a starting point for configuring your own custom board. +The easiest way to do so, when creating a :ref:`Zephyr repository application `, is to create a copy of these folders under :file:`sdk-nrf-next/boards/arm/your_custom_board_name` (for the ARM configuration files) and :file:`sdk-nrf-next/boards/riscv/your_custom_board_name` (for the Risc-V configuration files), respectively. + +.. caution:: + Do not modify the configuration files related to the Secure Domain (:file:`*_cpusec` in the ARM folder) and the System Controller (:file:`*_cpusys` in the Risc-V folder). + +You must edit the :file:`.dts` and :file:`.overlay` files for your project to match your board configuration, similarly to any new board added to the |NCS| or Zephyr. + +See the following documentation pages for more information: + +* The :ref:`zephyr:devicetree` documentation to familiarize yourself with the devicetree language and syntax +* The :ref:`ug_nrf54h20_configuration` page for more information on how to configure your DTS files for the nRF54H20 SoC. +* The :ref:`zephyr:zephyr-repo-app` page for more information on Zephyr application types. +* The :ref:`dm_adding_code` documentation for details on the best user workflows to add your own code to the |NCS|. + +.. note:: + The configuration of board files is based on the `nRF54H20 common SoC files`_. + Each new |NCS| revision might change these files, breaking the compatibility with your custom board files created for previous revisions. + Ensure the compatibility of your custom board files when migrating to a new |NCS| release. + +Configure, generate, and flash BICR +*********************************** + +The Board Information Configuration Registers (BICR) are non-volatile memory (NVM) registers that contain information on how the nRF54H20 SoC must interact with other board elements, including the information about the power and clock delivery to the SoC. +The power and clock control firmware uses this information to apply the proper regulator and oscillator configurations. + +.. caution:: + You must ensure that the configuration is correct. + An incorrect configuration can damage your device. + +BICR allows for the configuration of various components on your custom board, like the following: + +* Power rails +* Low-frequency oscillator +* High-frequency oscillator (HFXO) +* GPIO ports power and drive control +* Tamper switches +* Active shield channels + +You can find the details of each register contained in BICR in the relevant `BICR register's PDF file`_. +When not set, the register's default value is ``0xFFFFFFFF``. + +The ``LFOSC.LFXOCAL`` register is used by the device to store the calibration of the LFXO. + +When ``LFOSC.LFXOCAL`` is ``0xFFFFFFFF`` at device boot, the firmware recalibrates the LFXO oscillator and writes the calibration data to the ``LFOSC.LFXOCAL`` register. +This is useful when making a change on the PCB (for example, when changing the crystal). +This initial calibration is only performed once. +Each subsequent start will use this initial calibration as the starting point. + +BICR configuration +================== + +The nRF54H20 PDK BICR configuration can be found in the board configuration directory as :file:`boards/arm/nrf54h20dk_nrf54h20/nrf54h20soc1_pdk_bicr.dtsi`. +This file is used by the |NCS| build system to generate a corresponding HEX file. +You can start from this file when editing the values of the devicetree properties inside your custom board folder (:file:`boards/arm/your_custom_board`), according to your board configuration. + +Generating the BICR binary +========================== + +To generate the BICR binary, you must first set the Kconfig option :kconfig:option:`CONFIG_INCLUDE_BICR` to ``y``. +When running ``west build``, the build system then runs the BICR devicetree node through `nrf-regtool`_ to create the relevant HEX file (:file:`bicr.hex`) at build time. +Based on the peripheral definition extracted from the nRF54H20 SVD file, the modified registers from the configuration are mapped into their relevant position in memory. + +.. note:: + If the build system cannot locate the ``bicr`` node inside your custom board's devicetree, or if you did not create a custom :file:`.dtsi` file for it, the BICR generation cannot progress, and the build system will skip it. + +You can find the generated :file:`bicr.hex` file in the :file:`build_dir/zephyr/`. +The presence of a ``bicr`` node in the application devicetree will automatically trigger a build of the BICR binary, and will place this file alongside the other binary outputs such as ``zephyr.hex`` and ``uicr.hex``. + +Flashing the BICR binary +======================== + +After the nRF Connect SDK build system generates the BICR binary, you must flash this binary manually. +The content of BICR should be loaded to the SoC only once and should not be erased nor modified unless the PCB layout changes. +To manually flash the generated :file:`bicr.hex` file to the SoC, use ``nrfjprog`` as follows:: + + nrfjprog --snr ${FPGA_SEGGER_ID} --coprocessor CP_SECURE -f nrf54h --program bicr.hex --verify + nrfjprog --coprocessor CP_SECURE --erasepage 0xfff8000 + nrfjprog --coprocessor CP_SECURE --erasepage 0xfffa000 + +You need to follow this flashing process only one time, as the PCB configuration will not change. + +Verify the Life Cycle State (LCS) of the SoC +******************************************** + +To successfully run your custom application on your custom board, the SoC must have its Lifecycle State (LCS) set to ``RoT`` (meaning Root of Trust). +To verify that, run nrfjprog from the nRF Command Line Tools version 10.23.3_ec as follows:: + + nrfjprog -s --memrd 0x0E000084 --w 32 --n 8 + +If nrfjprog returns ``0x2000`` twice, the LCS of the SoC is set to ``RoT``. +If nrfjprog returns ``0x1000`` twice, the LCS of the SoC is set to ``EMPTY``, meaning no LCS is set, and it needs to be switched to ``RoT``. + +If you get the following error, the SoC is in ROM boot mode:: + + [error] [ Client] - Encountered error -90: Command read_memory_descriptors executed for 1 milliseconds with result -90 + [error] [ Worker] - Ap-protect is enabled, can't read memory descriptors. + [error] [ Client] - Encountered error -90: Command read executed for 80 milliseconds with result -90 + [error] [haltium] - Device responded to command with error status in ADAC packet: INVALID_COMMAND (0x7FFF). + [error] [ Worker] - Access protection is enabled, can't access memory. + ERROR: The operation attempted is unavailable due to readback protection in + ERROR: your device. Please use --recover to unlock the device. + NOTE: For additional output, try running again with logging enabled (--log). + NOTE: Any generated log error messages will be displayed. + +Switch to ``NORMAL`` mode first, then run again the previous command:: + + nrfjprog -s --bootmode NORMAL + nrfjprog -s --memrd 0x0E000084 --w 32 --n 8 + +Switch LCS to RoT +================= + +To transition the LCS to ``RoT``, do the following: + +1. Program BICR and secdom:: + + nrfjprog -f nrf54h --coprocessor CP_SECURE --program /*insert_path_to_your_build_directory_here*/secdom/src/secdom-build/zephyr/zephyr.hex --verify + nrfjprog -f nrf54h --coprocessor CP_SECURE --program bicr.hex --verify + +#. Run these commands:: + + nrfjprog --coprocessor CP_SECURE --memwr 0x0E000108 --val 0x40000 + nrfjprog --coprocessor CP_SECURE --memwr 0x0E00010C --val 0x0E003000 + + nrfjprog --family nrf54h --bootmode ROM + nrfjprog --family nrf54h --adac lcs_change PSA_ROT_PROVISIONING --single-step + nrfjprog --family nrf54h --bootmode NORMAL + +#. Flash your application using west:: + + west flash + +#. Verify if the LCS is set to ``RoT``:: + + nrfjprog --memrd 0x0E000084 --w 32 --n 8 + + If nrfjprog returns ``0x2000`` twice, the LCS of the SoC is correctly set to ``RoT``. + +Create or modify your application for your custom board +******************************************************* + +You can now create or modify your application for your custom board. +When doing so, consider the following: + +* When reusing the |NCS| applications and samples, you must provide board-specific overlay files when such files are needed. + For general information on configuration overlays, see :ref:`configure_application`. + + However, you must consider the following nRF54H20-specific differences: + + * The application might require board overlays for multiple cores. + In this case, ensure that these overlays are consistent with each other. + +* When creating a new application specific to your new board, DTS board files can contain all necessary configurations, and no overlay file is needed. + However, the same limitations regarding the consistency and UICR configuration apply, but should be kept on the board files level. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_debugging.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_debugging.rst new file mode 100644 index 00000000000..b8f0d52ab52 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_debugging.rst @@ -0,0 +1,124 @@ +:orphan: + +.. _ug_nrf54h20_debugging: + +nRF54H20 debugging +################## + +.. contents:: + :local: + :depth: 2 + +The main recommended tool for debugging in the |NCS| for the limited sampling of the nRF54H20 DK is the `GNU Project Debugger`_ (GDB tool). + +When working from the command line, you can use west with the GDB tool. +For details, read the :ref:`Debugging with west debug ` section on the :ref:`zephyr:west-build-flash-debug` page in the Zephyr documentation. + +A useful tool for debugging the communication over Bluetooth is the `nRF Sniffer for Bluetooth LE`_. +The nRF Sniffer allows you to look into data exchanged over-the-air between devices. + +Debug configuration +******************* + +Set the following Kconfig options to ``y`` for the images running on the cores you want to debug: + +* :kconfig:option:`CONFIG_DEBUG_OPTIMIZATIONS` - This option limits the optimizations made by the compiler to only those that do not impact debugging. +* :kconfig:option:`CONFIG_DEBUG_THREAD_INFO` - This option adds additional information to the thread object so that the debugger can discover the threads. + This will work for any debugger. + +Debug configurations +******************** + +Some applications and samples provide a specific configuration that enables additional debug functionalities. +You can select custom configurations when you are :ref:`configuring the build settings `. + +Debugging multiple cores +************************ + +To debug only the Application core firmware, a single debug session is sufficient. +To debug the firmware running also on the other cores, you need to set up a separate debug session for each one of the cores you want to debug. +When debugging another core, the application core debug session runs in the background and you can debug both cores if needed. + +If you want to reset the other cores while debugging, make sure to first reset the application core and execute the code. + +Using GDB as an external debugger +********************************* + +An external debugger can access the device using the Debug Access Port (DAP). +The DAP is a standard Arm® CoreSight™ serial wire debug port (SWJ-DP) that implements the serial wire debug (SWD) protocol with a two-pin serial interface. + +There are several access ports that connect to different parts of the system: + + * AHB-AP 0: Application core access port ID + * AHB-AP 1: Radio core access port ID + * AHB-AP 2: Secure domain access port ID + * AHB-AP 3: Auxiliary access port ID + * CTRL-AP 4: Device level control access port ID + * APB-AP 5: CoreSight™ subsystem access port ID + +The following sections describe how to debug the nRF54H20 using GDB as the external debugger with J-link. + +.. note:: + J-Link version 7.80c is required. + +Selecting the core +================== + +To debug a specific core using ``JLinkExe`` do the following: + +1. Run J-Link on the Application core:: + + JLinkExe -USB -if SWD -Device Cortex-M33 + + You can use this command to run J-Link also on other Arm cores. + You can find the ``SEGGER-ID`` as follows: + + * Check the ``SEGGER ID`` printed on the label on the bottom side of the DK. + * Run the ``nrfjprog --ids`` command. + + If just one DK is connected to the machine, defining ``SEGGER-ID`` is not necessary. + If more than one DK is connected to the machine and ``SEGGER-ID`` is undefined, a pop up window will appear where you can manually select the ID of the DK you want to run J-Link on. + + .. note:: + PPR core debugging is not functional in the initial limited sampling. + +#. Connect to the Application core:: + + exec CORESIGHT_SetIndexAHBAPToUse = + connect + + ```` is the ID of the access port. + +J-Link script files +=================== + +You can also create J-Link script files in your local directory and add them to a GDB server call for a remote debugging session. + +1. Create a script file with the following content:: + + void ConfigTargetSettings(void) { + J-Link_CORESIGHT_AddAP(, CORESIGHT_AHB_AP); + CORESIGHT_IndexAHBAPToUse = ; + } + +2. Add the script file to the GDB server call:: + + -scriptfile [*full_path/to/script_file_name*] + +Debug logging +************* + +You can use the logging system to get more information about the state of your application. +Logs are integrated into various modules and subsystems in the |NCS| and Zephyr. +These logs are visible once you configure the logger for your application. + +You can also configure log level per logger module to, for example, get more information about a given subsystem. +See :ref:`ug_nrf54h20_logging` for details on how to enable and configure logs on the nRF54H20 DK. + +Debugging stack overflows +************************* + +One of the potential root causes of fatal errors in an application are stack overflows. +Read the Stack Overflows section on the :ref:`zephyr:fatal` page in the Zephyr documentation to learn about stack overflows and how to debug them. + +You can also use a separate module, such as Zephyr's :ref:`zephyr:thread_analyzer`, to make sure that the stack sizes used by your application are big enough to avoid stack overflows. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_gs.rst new file mode 100644 index 00000000000..1bc1bfb5bcb --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_gs.rst @@ -0,0 +1,147 @@ +:orphan: + +.. _ug_nrf54h20_gs: + +Getting started with the nRF54H20 DK +#################################### + +.. contents:: + :local: + :depth: 2 + +This section gets you started with your nRF54H20 Development Kit (DK) using the |NCS|. +It tells you how to install the :ref:`multicore_hello_world` sample and perform a quick test of your DK. + +If you have already set up your nRF54H20 DK and want to learn more, see the following documentation: + +* :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. +* ``ug_nrf54`` documentation for more advanced topics related to the nRF54H20. + +If you want to go through an online training course to familiarize yourself with Bluetooth Low Energy and the development of Bluetooth LE applications, enroll in the `Bluetooth LE Fundamentals course`_ in the `Nordic Developer Academy`_. + +.. _ug_nrf54h20_gs_requirements: + +Minimum requirements +******************** + +Make sure you have all the required hardware and that your computer has one of the supported operating systems. + +Hardware +======== + +* nRF54H20 DK +* USB-C cable + +Software +======== + +On your computer, one of the following operating systems: + +* Microsoft Windows +* Ubuntu Linux +* macOS + +|supported OS| + +You also need to install `Git`_ or `Git for Windows`_ (on Linux and Mac, or Windows, respectively). + +.. _ug_nrf54h20_gs_test_blinky: + +Testing with the Blinky sample +****************************** + +The nRF54H20 DK comes preprogrammed with the :zephyr:code-sample:`blinky` sample. + +Complete the following steps to test that the DK works correctly: + +1. Connect the USB-C end of the USB-C cable to the **IMCU USB** port the nRF54H20 DK. +#. Connect the other end of the USB-C cable to your PC. +#. Move the **POWER** switch to **On** to turn the nRF54H20 DK on. + The switch is located in the top left corner of the DK PCB. + +**LED1** will turn on and start to blink. + +If something does not work as expected, contact Nordic Semiconductor support. + +.. _nrf54h20_gs_installing_software: + +Installing the required software +******************************** + +On your computer, install `nRF Connect for Desktop`_. +You must also install a terminal emulator, such as `nRF Connect Serial Terminal`_ (from the nRF Connect for Desktop application) or the nRF Terminal (part of the `nRF Connect for Visual Studio Code`_ extension). + +.. _ug_nrf54h20_gs_sample: + +Programming the sample +********************** + +The :ref:`multicore_hello_world` sample is a multicore sample running on both the Application core (``cpuapp``) and the Peripheral Processor (PPR, ``cpuppr``). +It uses the ``nrf54h20dk_nrf54h20_cpuapp`` build target. + +To build and program the sample to the nRF54H20 DK, complete the following steps: + +1. Connect the nRF54H20 DK to you computer using the IMCU USB port on the DK. +#. Navigate to the :file:`nrf/samples/multicore/hello_world` folder containing the sample. +#. Build the sample for application and radio cores by running the following command:: + + west build -p -b nrf54h20dk_nrf54h20_cpuapp -T sample.multicore.hello_world.nrf54h20dk_cpuapp_cpurad . + +#. Alternatively, build the sample for the application and PPR cores by running the following command:: + + west build -p -b nrf54h20dk_nrf54h20_cpuapp -T sample.multicore.hello_world.nrf54h20dk_cpuapp_cpuppr . + +#. Program the sample using nrfjprog. + If you have multiple Nordic Semiconductor devices, make sure that only the nRF54H20 DK you want to program is connected. + + .. code-block:: console + + west flash + +The sample will be automatically built and programmed on both the Application core and the Peripheral Processor (PPR) of the nRF54H20. + +.. _nrf54h20_sample_reading_logs: + +Reading the logs +**************** + +With the :ref:`multicore_hello_world` sample programmed, the nRF54H20 DK outputs logs for the application core and the configured remote processor. +The logs are output over UART. + +To read the logs from the :ref:`multicore_hello_world` sample programmed to the nRF54H20 DK, complete the following steps: + +1. Connect to the DK with a terminal emulator (for example, `nRF Connect Serial Terminal`_) using the :ref:`default serial port connection settings `. +#. Press the **Reset** button on the PCB to reset the DK. +#. Observe the console output for both cores: + + * For the application core, the output should be as follows: + + .. code-block:: console + + *** Booting nRF Connect SDK zephyr-v3.5.0-3517-g9458a1aaf744 *** + Hello world from nrf54h20dk_nrf54h20_cpuapp + Hello world from nrf54h20dk_nrf54h20_cpuapp + ... + + * For the remote core, e.g. PPR, the output should be as follows: + + .. code-block:: console + + *** Booting nRF Connect SDK zephyr-v3.5.0-3517-g9458a1aaf744 *** + Hello world from nrf54h20dk_nrf54h20_cpuppr + Hello world from nrf54h20dk_nrf54h20_cpuppr + ... + +.. note:: + If no output is shown when using nRF Serial Terminal, select a different serial port in the terminal application. + +See the :ref:`ug_nrf54h20_logging` page for more information. + +Next steps +********** + +You are now all set to use the nRF54H20 DK. +See the following links for where to go next: + +* :ref:`ug_nrf54h20_architecture` for information about the multicore System-on-Chip, such as the responsibilities of the cores and their interprocessor interactions, the memory mapping, and the boot sequence. +* The :ref:`introductory documentation ` for more information on the |NCS| and the development environment. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_logging.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_logging.rst new file mode 100644 index 00000000000..0bf2410f214 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_logging.rst @@ -0,0 +1,190 @@ +:orphan: + +.. _ug_nrf54h20_logging: + +nRF54H20 logging +################ +.. contents:: + :local: + :depth: 2 + +To read logs on the nRF54H20 DK, you can use the following methods: + +* A direct UART connection to a specific core. +* Local domain logging with System Trace Macrocell (STM). + STM has two modes: + + * Standalone logging + * Assisted multicore logging + +For general information on how logging works in the |NCS|, consult the :ref:`ug_logging` and :ref:`zephyr:logging_api` documentation pages. + +nRF54H20 logging using a direct UART connection +*********************************************** + +Similarly to other SoCs from Nordic Semiconductor, to use a UART connection for reading logs, follow the :ref:`ug_logging_backends_uart` logging guide in the application development section. + +nRF54H20 logging using System Trace Macrocell (STM) +*************************************************** + +nRF54H20 domains contain ARM Coresight System Trace Macrocell (STM) hardware devices for collecting trace data from multiple domains, using either standalone logging or assisted multicore logging. +The STM uses memory-mapped registers to write trace data generated by the domains in the system. +It multiplexes the data as trace protocol data, formatted according to the MIPI System Trace Protocol (STP) v2, and synchronizes the data on a single output, such as a single UART. +This approach has a minimal cost on performance and code size, allowing for a non-intrusive collection of system debug-and-trace information. + +The STM implements a frontend of the Zephyr logging subsystem, allowing you to use the standard Zephyr logging API. + +.. note:: + + Currently, only the :ref:`multicore_hello_world` sample supports STM logging. + +Embedded Trace Router (ETR) +=========================== + +The Embedded Trace Router (ETR) is a hardware feature that provides a circular buffer in RAM for trace data. +It can trigger interrupts when the buffer is half-full or full, allowing the CPU to be woken up in time to handle the data. +The ETR buffer size is limited to 4 Kb, and it requires additional formatting with 16-byte frames. + +When using ETR, one of the cores is designated as a *proxy* to manage the trace data. + +.. note:: + Currently, the Secure Domain is the only core that can be designated as proxy. + +The proxy core is responsible for handling the data from the ETR and outputting it through the desired transport mechanism (like UART or USB). +The proxy core approach allows for on-chip data processing, offering more flexibility than the Trace Port Interface Unit (TPIU). +However, due to the limited size of the ETR buffer, there is a risk of data loss if not handled promptly. + +Standalone logging +================== + +The current implementation for the standalone logging mode with STM works as follows: + +1. All domains write the raw encoded log data to their own STM peripheral called the STM Extended Stimulus Port (STMESP). +#. The STMESP generates a data stream based on the register writes. +#. The STM multiplexes the data stream with streams from other domains, and it places them in the single memory buffer provided by the ETR. +#. The Secure Domain Firmware (SDFW), acting as the ETR-designated proxy, reads the buffer and decodes the raw encoded log data. +#. The SDFW outputs the logging data in a human-readable format over UART. + +Standalone logging leverages the frontend API of the Zephyr logging subsystem to select the stimulus ports and writes log messages directly to memory-mapped registers. +This method bypasses the need for string formatting functions and peripheral drivers, as the core writes directly to the STM port. + +Configuration +------------- + +To show the logs for a given domain in the UART output, you must enable the STM for that domain. + +To enable the STM for a domain, set the :kconfig:option:`CONFIG_LOG_STM` Kconfig option for that domain's image to ``y``. +The STM will be enabled by the build system in the configuration of the SDFW. + +Reading the logs +---------------- + +To read the STM log output on the UART, consult the following documentation pages: + +* If you want to use the *nRF Serial Terminal* from the |nRFVSC|, see the `nRF Terminal documentation`_ on the `nRF Connect for Visual Studio Code`_ documentation site. +* If you want to use PuTTY, see :ref:`putty`. + +.. note:: + To use UART in your application, the UART's node must be described in devicetree. + For more details, see :ref:`zephyr:devicetree-intro`. + +The following is an example log output:: + + [00:00:00.154,790] app/spsc_pbuf: alloc in 0x2f0df800 + [00:00:00.163,319] app/spsc_pbuf: alloc 0x2f0df800 wr_idx:20 + [00:00:00.181,112] app/spsc_pbuf: commit in 0x2f0df800 + [00:00:00.189,090] app/spsc_pbuf: commit 0x2f0df800, len:20 wr_idx: 44 + [00:00:00.202,577] rad/icmsg: mbox_callback + [00:00:00.214,750] rad/spsc_pbuf: claim 0x2f0df800 rd_idx:20 + [00:00:00.235,823] rad/spsc_pbuf: free 0x2f0df800 len:20 rd_idx: 44 + [00:00:00.244,507] rad/spsc_pbuf: read done 0x2f0df800 len:20 + [00:00:00.272,444] rad/host: ep recv 0x330021f0, len:20 + [00:00:00.283,939] rad/host: rx:00 exp:00 + [00:00:00.292,200] rad/icmsg: read 0 + [00:00:05.077,026] rad/spsc_pbuf: alloc in 0x2f0df000 + [00:00:05.077,068] rad/spsc_pbuf: alloc 0x2f0df000 wr_idx:44 + [00:00:05.077,098] rad/spsc_pbuf: commit in 0x2f0df000 + [00:00:05.077,134] rad/spsc_pbuf: commit 0x2f0df000, len:20 wr_idx + +Each log line contains a domain-related or core-related prefix between the log level and the module name, indicating the core that generated the log entry. +The following are the prefixes used to indicate the cores: + +.. csv-table:: nRF54H20 log prefixes + :header: "Core", "Prefix" + + Secure Domain, ``sec`` + Application core, ``app`` + Radio core, ``rad`` + System Controller (SysCtrl), ``sys`` + Fast Lightweight Processor (FLPR), ``flpr`` + Peripheral Processor (PPR), ``ppr`` + +Assisted multicore logging +========================== + +Assisted multicore logging uses dictionary-based logging to send messages without redundant strings to STM, and is based on the :ref:`logging_guide_dictionary` feature of the logging API provided by Zephyr. +Instead of including the format strings in the log messages, it logs the addresses (message IDs) where the strings are stored, which reduces the size of the logging subsystem. +If the data goes to the ETR buffer, the proxy core's responsibility is to dump this data. +The host PC, equipped with a decoder tool, translates these addresses back into human-readable text using a JSON database generated during the build process. + +When using logs, this method has the following advantages: + +* It reduces the size of the binary, as the strings used in the log messages are not stored in the binary itself. +* It reduces the amount of data that needs to be sent to and processed by the application core, as the string formatting is offloaded to the host side. + +Configuration +------------- + +To enable the assisted multicore logging for a domain, set the :kconfig:option:`CONFIG_LOG_STM_DICT` Kconfig option for that domain's image to ``y``. + +After building your application, a dictionary database file named :file:`log_database.json` will be generated in the :file:`build/zephyr` directory. +This file is crucial for decoding the logs and is updated with every build. + +Reading the logs +---------------- + +To read the dictionary-based STM log output, do the following: + +1. Set up the log capture. + + Use the ``nrfutil trace stm`` command to start capturing logs from the device, specifying the database configuration for each domain ID, as well as the serial port, the baud rate, and the output file name:: + + nrfutil trace stm --database-config 33:build/secdom/src/secdombuild/zephyr/log_dictionary.json,34:build/zephyr/log_dictionary.json --input-serialport /dev/ttyACM1 --baudrate 115200 --output-ascii out.txt + +#. Capture and decode the logs. + + nrfutil will capture the log data from the specified UART port and use the provided dictionary databases to decode the logs into a human-readable format. + The decoded logs will be saved in the specified output file (the :file:`out.txt` file in the previous example). + +#. Open the output file to review the decoded log messages. + + The file will contain timestamps and the log messages in a format that is human-readable. + +If the log capture fails to find a sync, rerun the capture process. + +.. note:: + Decoding artifacts or incorrect timestamps might occur when rerunning the process. + +Each log line contains a domain-related or core-related prefix between the log level and the module name, indicating the core that generated the log entry. +The following are the prefixes used to indicate the cores: + +.. csv-table:: nRF54H20 log prefixes + :header: "Core", "Prefix", "ID" + + Secure Domain, ``sec``, 0x21 + Application core, ``app``, 0x22 + Radio core, ``rad``, 0x23 + System Controller (SysCtrl), ``sys``, 0x2c + Fast Lightweight Processor (FLPR), ``flpr``, 0x2d + Peripheral Processor (PPR), ``ppr``, 0x2e + , ``mod``, 0x24 + +Additional considerations +------------------------- + +When using assisted multicore logging, consider the following: + +* Use optimized log macros (having up to 2 word size numeric arguments, like ``LOG_INF("%d %c", (int)x, (char)y)``) to improve the size and speed of logging. +* For memory constrained applications (for example, when running on the PPR or FLPR cores), disable the ``printk()`` function by setting both the :kconfig:option:`CONFIG_PRINTK` and :kconfig:option:`CONFIG_BOOT_BANNER` Kconfig options to ``n`` in your project configuration. +* When working with multiple domains, such as the Secure Domain and Application core, ensure that each database is prefixed with the correct domain ID. +* Some log messages might be dropped due to the limited size of the RAM buffer that stores STM logs. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_matter_thread.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_matter_thread.rst new file mode 100644 index 00000000000..f8783824c87 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_matter_thread.rst @@ -0,0 +1,299 @@ +:orphan: + +.. _ug_nrf54h20_matter_thread: + +Working with nRF54H20 and Matter and Thread +########################################### + +.. contents:: + :local: + :depth: 2 + +The nRF54H20 DK supports the following Matter and Thread samples: + +* :ref:`Matter door lock sample ` +* :ref:`Matter template sample ` +* :ref:`Thread CLI sample ` + +The Matter support is currently limited to Matter over Thread, and support for both Matter and Thread is currently :ref:`experimental `. +Read the following sections for more information about support in the nRF54H20 DK and the platform design for the nRF54H20 SoC. + +For more information about Matter and Thread in the |NCS|, read the documentation in the :ref:`ug_matter` and :ref:`ug_thread` protocol sections. + +Platform designs for the nRF54H20 SoC +************************************* + +Matter in the |NCS| supports the *System-on-Chip, multiprotocol* platform design for the nRF54H20 SoC using Matter over Thread. +You can read more about other available platform designs for Matter on the :ref:`Matter platform design page`. + +Thread in the |NCS| supports the *System-on-Chip, single protocol* and *System-on-Chip, multiprotocol* platform designs for the nRF54H20 SoC. +You can read more about other available platform designs for Thread on the :ref:`OpenThread architectures page`. + +For more information about the multiprotocol feature, see :ref:`ug_multiprotocol_support`. + +System-on-Chip, single protocol +=============================== + +In this design, the OpenThread stack runs on several cores and domains of a single nRF54H20 SoC. + +This platform designs is suitable for the following development kit: + +##TODO add to /includes/sample_board_rows.txt + +In this design: + +* The Application Core runs the OpenThread stack. +* The Radio Core runs the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver. +* The Secure Domain stores all the secure components, including keys and certificates. + It also manages the access to peripherals, memory, and other components. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. + +* The Global Domain manages clocks, power, global RAM, and global NVM. + +For more information, see :ref:`ug_nrf54h20_architecture_cpu`. + +The following figure demonstrates the architecture. +The Global Domain is not included. + +.. figure:: images/thread_platform_design_nRF54h20.svg + :alt: Multiprotocol Thread and Bluetooth LE architecture (nRF54H20) + + Single protocol Thread architecture on the nRF54H20 SoC + +System-on-Chip, multiprotocol +============================= + +In this design, the OpenThread stack and the Bluetooth® Low Energy (LE) stack run on several cores and domains of a single nRF54H20 SoC. + +This platform design is suitable for the following development kit: + +##TODO add to /includes/sample_board_rows.txt + +In this design: + +* The Application Core runs the OpenThread stack, and a part of the Bluetooth LE Controller. +* The Radio Core runs both the Bluetooth LE Controller and the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver. +* The Secure Domain stores all the secure components, including keys and certificates. + It also manages the access to peripherals, memory, and other components. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. + +* The Global Domain manages clocks, power, global RAM, and global NVM. + +For more information, see :ref:`ug_nrf54h20_architecture_cpu`. + +The following figure demonstrates the architecture. +The Global Domain is not included. + +.. _nrf54h20_platform_multi_figure: + +.. figure:: images/thread_platform_design_nRF54h20_multi.svg + :alt: Multiprotocol Thread and Bluetooth LE architecture (nRF54H20) + + Multiprotocol Thread and Bluetooth LE architecture on the nRF54H20 SoC + +Matter over Thread +================== + +In this design, the Matter stack, the OpenThread stack, and the Bluetooth® Low Energy (LE) stack run on several cores and domains of a single nRF54H20 SoC. + +This platform design is suitable for the following development kit: + +##TODO add to /includes/sample_board_rows.txt + +In this design: + +* The Application Core runs the Matter stack, the OpenThread stack, and a part of the Bluetooth LE Controller. +* The Radio Core runs both the Bluetooth LE Controller and the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver. +* The Secure Domain stores all the secure components, including keys and certificates. + It also manages the access to peripherals, memory, and other components. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. + +* The Global Domain manages clocks, power, global RAM, and global NVM. + +For more information, see :ref:`ug_nrf54h20_architecture_cpu`. + +Refer to the :ref:`nrf54h20_platform_multi_figure` figure to see the architecture of the SoC. +The Global Domain is not included. + +Additional requirements on the nRF54H20 DK +****************************************** + +In addition to the standard requirements for the |NCS|, such as the :ref:`ug_matter_gs_tools_gn` for Matter, you need the following to run Matter-enabled or Thread-enabled applications on the nRF54H20 DK: + +* For DFU - J-Link and a USB cable. +* nrfjprog from the `nRF Command Line Tools`_. + +Configuring Matter and Thread on the nRF54H20 DK +************************************************ + +Currently, only the configuration for Matter over Thread is supported for Matter. +Follow the configuration steps on the :ref:`ug_matter_gs_testing` page to configure the Matter environment for the supported Matter samples. + +Currently, only the :ref:`ot_cli_sample` sample is supported for Thread. +See the sample documentation for how to configure it. + +The Matter and Thread samples can work on the corresponding networks with standard devices of the same protocol. + +Programming Matter and Thread samples on the nRF54H20 DK +======================================================== + +To program the compatible Matter or Thread samples on the nRF54H20 DK, follow the :ref:`ug_nrf54h20_gs_sample` steps. +Read also programming guides prepared for specific Matter samples: :ref:`Matter door lock sample `, and :ref:`Matter template sample `. + +.. note:: + :ref:`Testing using Bluetooth LE with Nordic UART Service ` on the :ref:`Matter door lock sample ` is disabled by default. + +Logging for Matter and Thread samples on the nRF54H20 DK +======================================================== + +To read logs for Matter samples on the nRF54H20 DK, complete the following steps: + +1. Connect to the nRF54H20 DK using a USB cable. +#. Select the first available port to read the logs from. + +For more information, see :ref:`ug_nrf54h20_logging`. + +.. _ug_nrf54h20_matter_thread_matter_wifi: + +Matter over Wi-Fi +================= + +Matter over Wi-Fi is currently supported on the :ref:`Matter door lock sample ` and :ref:`Matter template sample `. + +In this design, the Matter stack, the Wi-Fi stack, and the Bluetooth® Low Energy (LE) stack run on several cores and domains of a single nRF54H20 SoC. + +To run Matter over Wi-Fi on the nRF54H20 DK you need the additional ``nrf7002_ek`` shield attached through the nRF54H20 DK to the nRF7002 EK interposer board. + +In this design: + +* The Application Core runs the Matter stack, the Wi-Fi stack, and a part of the Bluetooth LE Controller. +* The Radio Core runs both the Bluetooth LE Controller and the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver. +* The Secure Domain stores all the secure components, including keys and certificates. + It also manages the access to peripherals, memory, and other components. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. + +* The Global Domain manages clocks, power, global RAM, and global NVM. + +To build the sample with Matter over Wi-Fi support run the following command: + +.. code-block:: console + + west build -b nrf54h20dk_nrf54h20_cpuapp -- -DSHIELD=nrf700x_nrf54h20dk -DCONFIG_CHIP_WIFI=y + + +.. _ug_nrf54h20_matter_thread_suit_dfu: + +SUIT Device Firmware Upgrade support on the nRF54H20 DK +======================================================= + +The :ref:`SUIT Device Firmware Upgrade ` feature has been implemented on the nRF54H20 DK and you can use it in the :ref:`Matter door lock sample `. +In this solution, both Application and Radio Cores can be upgraded sequentially to the newest version using :ref:`SUIT hierarchical manifests `. +The SUIT DFU feature uses :ref:`SUIT manifests ` that contain components and images of the firmware and are used by the Secure Domain to replace, verify and run the firmware. +In the Matter Lock sample, we use the Simple Management Protocol (SMP) over Bluetooth LE transport to deliver the new firmware to the device's DFU partition and then the SUIT processor installs the image according to the instructions that are described in the manifest. +By default, the root manifest contains both Application and Radio Core images, but for the Matter sample the images need to be split to the separate cores and perform upgrades sequentially. +Currently, there is no protection against incompatibility between the new Radio Core and old Application Core images, so you need to ensure that compatibility. +We have prepared manifest templates in the ``configurations/nrf54h20dk_nrf54h20_cpuapp`` directory in the Matter lock sample which are prepared to generate two separate SUIT envelopes - one for the Application Core and another for the Radio Core. They are as follows: + + * :file:`app_envelope.yaml.jinja2` - Contains the procedures for SUIT directives that allow for the Application Core image to be updated. + * :file:`app_envelope.yaml.jinja2.digest` - Contains the digital signature of the SUIT manifest prepared for the Application Core image. + * :file:`multiprotocol_rad_envelope.yaml.jinja2` - Contains the procedures for SUIT directives that allow for the Radio Core image to be updated. + * :file:`multiprotocol_rad_envelope.yaml.jinja2.digest` - Contains the digital signature of the SUIT manifest prepared for the Radio Core image. + * :file:`root_hierarchical_envelope.yaml.jinja2` - Contains the procedures for SUIT directives to run the current firmware. + * :file:`root_hierarchical_envelope.yaml.jinja2.digest` - Contains the digital signature of the SUIT manifest prepared for running the current firmware. + +You can edit the templates for other purposes. +To learn how to do edit the manifest templates, see the :ref:`ug_nrf54h20_suit_customize_dfu` guide. + +To build the firmware with the SUIT DFU support, run the following command with the *number* replaced with the new image number, that should be higher than the previous one: + +.. parsed-literal:: + :class: highlight + + west build -b nrf54h20dk_nrf54h20_cpuapp -- -DCONFIG_SUIT_ENVELOPE_SEQUENCE_NUM=*number* + +You can perform a DFU using the nRF Connect Device Manager mobile application or the :ref:`Mcumgr command-line tool `. +After building the sample you can find two SUIT envelopes created in the build directory and depending on the core type you can search for: + + * the :file:`build/zephyr/app.suit` file to get the SUIT envelope for the Application Core. + * the :file:`build/multiprotocol_rpmsg/zephyr/multiprotocol_rpmsg_subimage.suit` file to get the SUIT envelope for the Radio Core. + +To learn how to perform a DFU using the nRFConnect Device Manager mobile application read instructions in the ``suit smp transfer `` guide. + +Performing DFU on nRF54H20 DK using Mcumgr command-line tool +------------------------------------------------------------ + + 1. Follow the instructions in the :ref:`Mcumgr command-line tool ` guide to install Mcumgr. + #. Press **Button 1** to enable Bluetooth LE SMP advertising on the nRF54H20 DK. + #. Run the following command to upgrade the Radio Core: + + .. parsed-literal:: + :class: highlight + + mcumgr --conntype ble --hci *hci number* --connstring peer_name=*peer name* image upload *path to multiprotocol_rpmsg_subimage.suit* -n 0 -w 1 + + Where: + + * *hci number* is the Bluetooth LE device ID on your host device (by default it is ``0``). + * *peer name* is the Bluetooth LE name which is advertised by the nRF54H20 DK (by default ``"Matter Lock"``). + * *path to multiprotocol_rpmsg_subimage.suit* is a path to the SUIT envelope that contains Radio Core image. + + For example: + + .. parsed-literal:: + :class: highlight + + mcumgr --conntype ble --hci 0 --connstring peer_name="MatterLock" image upload build/multiprotocol_rpmsg/zephyr/multiprotocol_rpmsg_subimage.suit -n 0 -w 1 + + #. Press **Button 1** to enable Bluetooth LE SMP advertising on the nRF54H20 DK again, because the previous operation disabled it after applying the image. + #. Run the same command as in Step 3 to upgrade the Application Core image, but this time provide a path to the ``app.suit`` file. + + For example: + + .. parsed-literal:: + :class: highlight + + mcumgr --conntype ble --hci 0 --connstring peer_name="MatterLock" image upload build/zephyr/app.suit -n 0 -w 1 + + +Implementing support for the nRF54H20 DK +======================================== + +If you want to implement support for the nRF54H20 DK in your Matter-enabled or Thread-enabled application, read the :ref:`ug_nrf54h20_configuration` guide. + +.. _ug_nrf54h20_matter_thread_limitations: + +Limitations for Matter and Thread on the nRF54H20 DK +**************************************************** + +Matter and Thread support has the following limitations on the nRF54H20 DK: + +* DFU over Matter or Serial Link is not yet implemented. +* The current implementation is not power-optimized. +* The cryptographic operations related to Matter and Thread are performed on the Application Core, rather than on the Secure Domain. +* The ``west flash --erase`` command is blocked. + See :ref:`ug_nrf54h20_gs_sample` for more information. +* The factory reset functionality does not work properly. + After clearing all NVM storage, the device can not reboot automatically and falls into a hard fault. + + As a workaround, press the reset button on the nRF54H20 DK board after performing a factory reset. +* Matter over Thread commissioning might be unstable due to the lack of true random generator support on nRF54H20. + + After each reboot or factory reset, the device will always have the same Bluetooth LE and IEEE 80215.4 addresses. + This might impact working within the Thread network because after the second and following connections, Thread Border Router will reject these connections until deleted from the database and commissioning to Matter will take more and more time. + + As a workaround, after each factory reset and before performing the next commissioning to Matter, connect to the device's serial port and run the following command: + + .. parsed-literal:: + :class: highlight + + ot extaddr *address* + + Replace the *address* argument with an 8-byte randomly generated MAC address, for example ``87fb47d5730ac0a0``. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_nrf7002ek.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_nrf7002ek.rst new file mode 100644 index 00000000000..5cae530c9b1 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_nrf7002ek.rst @@ -0,0 +1,65 @@ +:orphan: + +.. _ug_nrf54h20_nrf7002ek: + +Working with the nRF54H20 DK and the nRF7002 EK +############################################### + +.. contents:: + :local: + :depth: 2 + +The `nRF7002 EK`_ is an evaluation kit featuring the nRF7002 Wi-Fi® 6 companion IC. +The kit can be used to provide Wi-Fi connectivity to the nRF54H20 DK. + +.. figure:: images/nRF7002ek.png + :alt: nRF7002 EK + + +Pin assignment for the nRF54H20 DK GPIO +======================================= + +The interface connector of the nRF7002 EK can be connected to the nRF54H20 DK GPIO as described in the following table: + ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| nRF7002 EK signal | nRF54H20 DK GPIO signal | EK connector and pin | Function | ++================================+=========================+======================+==================================+ +| BUCK_EN | **P0.08** | **P9.2** | Enable power to nRF7002 | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| IOVDDEN | **P0.09** | **P9.1** | Enable power to I/O interface | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| COEX STATUS0 | **P0.02** | **P9.3** | Coexistence status 0 | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| COEX REQUEST | **P0.03** | **P9.4** | Coexistence request from host | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| COEX GRANT | **P0.04** | **P9.5** | Coexistence grant to host | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SWITCH CONTROL0 | **P0.05** | **P9.6** | Switch control 0 | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SWITCH CONTROL1 / COEX STATUS1 | **P0.06** | **P9.7** | Switch control 1 / Coex status 1 | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| HOST IRQ | **P0.10** | **P9.8** | Interrupt request to host | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SPI CS | **P2.09** | **P10.3** | SPI Slave select | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SPI MOSI | **P2.07** | **P10.4** | SPI Slave IN | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SPI MISO | **P2.08** | **P10.5** | SPI Slave OUT | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| SPI CLK | **P2.00** | **P10.6** | SPI Clock | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| 5V | **P5.3** | **P7.5** | 5 V to nRF7002 EK | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| GND | **P5.1** | **P7.6** | GND | ++--------------------------------+-------------------------+----------------------+----------------------------------+ +| VDD | **P5.4** | **P7.1** | 1.8 V to nRF7002 EK | ++--------------------------------+-------------------------+----------------------+----------------------------------+ + +These connectors are on the bottom side of the nRF7002 EK. +You can make the connections with a flyer wire between the headers **P2**, **P0**, and **P5** on nRF54H20 DK and **P9**, **P10**, and **P7** on nRF7002 EK. + +Supported samples +================= + +The :ref:`wifi_shell_sample` sample provides support for the nRF54H20 DK used with the nRF7002 EK. +For more information, visit its :ref:`documentation `. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_compare_other_dfu.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_compare_other_dfu.rst new file mode 100644 index 00000000000..ae32254c9a9 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_compare_other_dfu.rst @@ -0,0 +1,37 @@ +:orphan: + +.. _ug_nrf54h20_suit_compare_other_dfu: + +DFU and bootloader comparison +############################# + +The Nordic Semiconductor implementation of the :ref:`SUIT procedure ` is the only supported bootloader and Device Firmware Update (DFU) procedure for the nRF54H Series of System on Chips (SoC). +It provides a more flexible and tailored DFU experience compared to the MCUboot procedure and |NSIB| to better fit the needs of the SoC's multiple cores and transports. +See the diagram and comparison table below for further comparison. + +.. figure:: images/nrf54h20_suit_mcuboot_comparison.png + :alt: MCUboot and SUIT architecture comparison + + MCUboot and SUIT architecture comparison + ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Characteristic | MCUboot | SUIT | nRF Secure Immutable Bootloader | ++==========================+=========================================================================+===================================================================================================================+===========================================================================================+ +| Primary function | Bootloader and DFU | Flexible, script-based DFU system | Secure Immutable Bootloader | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Customization | Built by users; partitions customized with Kconfig options and DTS. | SDFW provided by Nordic, delivered in binary form. | Limited; focused on initial boot security. | +| | Kconfig and DTS configurable with multi-image builds or sysbuild. | Customizable with manifests and configuration. | | +| | Becomes static post-compilation. | | | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Slot management | Symmetrical primary and secondary slot style. | Single DFU partition; components act as slots. | Not applicable for firmware updates. | +| | Primary slot is where the system is executed from (by default). | The DFU partition size can be located anywhere in the nonvolatile memory, accessible in the application core. | | +| | Secondary slot is the destination for the DFU (by default). | Information about the location of the DFU is not hardcoded in the SDFW and can be changed between updates. | | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Slot characteristics | Equal primary and secondary slot sizes lead to high memory overhead. | Single DFU partition with customizable component sizes. | Highly efficient due to immutable design. | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Slot definition | Static definition; challenging to change post-deployment. | Technical possibility to change component definitions between updates. | Fixed and immutable; no post-deployment changes. | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Invocation process | Limited customization through metadata. | Flexible customization within the manifest (metadata). | Authenticated firmware execution; no update mechanism post-boot. | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Flash memory layout | Specific allocations for primary and secondary slots. | Single DFU partition with flexible component slots. | OTP regions for provisioned data; specific layout for boot and application partitions. | ++--------------------------+-------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_components.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_components.rst new file mode 100644 index 00000000000..e4443c37fb2 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_components.rst @@ -0,0 +1,127 @@ +:orphan: + +.. _ug_nrf54h20_suit_components: + +SUIT components +############### + +.. contents:: + :local: + :depth: 2 + +:ref:`Components ` are the fundamental elements that the SUIT manifest operates on and are declared in :ref:`suit-common ` (which is represented as the bstr CBOR value ``suit-common`` within the manifest). +Using and modifying the component types allows for operational, fine-tuned customization of the DFU procedure. + +See the :ref:`component_ID` section for more information. + +Component types +*************** + +The current available component types are as follows: + +* ``MEM`` - MCU memory-mapped slot (such as the MRAM or RAM). + This is used to define a specific area in the memory where an image can be placed, and by default, it is defined automatically from the build system. + The memory components are the abstractions that map to memory locations on the device's memory. + +* ``CAND_MFST`` - The candidate manifest component refers to the dependency candidate in the envelope or in the download cache. + Different values allow you to declare more than one component of that type per manifest. + It points to the candidate manifest instead of copying the content to a memory location. + For example, if an envelope contains all the candidate manifests, then you can refer to the manifest in the envelope using the candidate manifest component. + +* ``CAND_IMG`` - The candidate image component refers to the integrated payload in the candidate envelope or payload in the download cache. + For example, the ``CAND_IMG`` component allows you to validate the candidate before the installation step is performed. + + The following example shows the installation procedure, including the checking of the coherency of the image by using the ``CAND_IMG`` component. + During the installation process, ``directive-fetch`` puts information about the location of the image into component candidate image ``0``. + ``condition-image-match`` performs the digest check on the candidate image ``0`` and verifies the digest of the image. + After the verification, the installation of the image at the final location is done by the ``directive-copy``. + + .. code-block:: console + + components: [ + [MEM/2/0xeff8000/0x10000], + [CAND_IMG/0] + ] + + install: [ + directive-set-component-index 1, + directive-override-parameters { + uri: '#file.bin' + image-digest: [ + algorithm-id: "sha256", + digest-bytes: '00112233445566778899aabbccddeeff0123456789abcdeffedcba9876543210' + ] + }, + directive-fetch, + condition-image-match, + directive-set-component-index 0, + directive-override-parameters { + source-component: 1 + }, + directive-copy + ] + +* ``INSTLD_MFST`` - The installed manifest component is the slot for the envelope containing the installed manifest, which holds the severed manifest and its authentication block. + It points to the manifest, which is already installed. + +* ``SOC_SPEC`` - SOC-specific components are reserved for Nordic internal usage. + The installation of this component type goes beyond memory CPU-like operations. + +* ``CACHE_POOL`` - The ``CACHE_POOL`` is a space where images downloaded during the ``payload-fetch`` sequence execution can be stored and are ready for installation. + In the context of the Application Domain, the ``payload-fetch`` sequence can contain instructions to fetch images from external sources (such as an HTTP server). + Typically, these images must not be installed directly into the destination components by the ``payload-fetch`` sequence. + They must be verified and installed by the ``install`` sequence, executed in the context of the SDFW or bootloader. + + + ``CACHE_POOL`` allows you to push the envelope to the device, but without any payloads. + When the manifest is processed, it may evaluate what is currently installed on the device. + For example, the manifest calculates the digests of specific images, and based on those calculations, it fetches missing images from outside. + + When the value of ``CACHE_POOL`` is: + + * ``0`` - describes a location in the DFU partition, located right after the candidate envelope. + When the ``CACHE_POOL`` value is ``0``, it is directly accessible by the SDFW, therefore, it may be used to store a companion image that, when executed on the Application MCU, allows the SDFW to access otherwise unsupported memory areas (such as external flash). + + * ``1..n`` - describes a deployment-specific ``CACHE_POOL`` such as, for example, external flash partitions or other MRAM partitions. + It defines multiple different cache pools. + + **Benefits of the ``CACHE_POOL`` component** + + The following are the benefits of the ``CACHE_POOL`` component: + + * Memory optimization - ``CACHE_POOL`` component allows you to conditionally pull missing images from the Application Domain or application framework before installation starts. + It helps in the gradual update process by installing one of the two images in the first installation step and then repeating the process to install another image. + + * Save on data transfer costs - The manifest and the candidate manifest only pull the missing images instead of pushing all the images in the update. + +.. _component_ID: + +Component ID parameters +*********************** + +The component types that can be modified at this time are listed in the following table. +Fields indicate different parameters for component types. + ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| Field 0 - Type | Field 1 | Field 2 | Field 3 | Field 4 | Component ID - example | ++======================+========================================================+========================+========================+==============+==================================================================================+ +| ``MEM`` | CPU ID: ``int`` | Slot address: ``uint`` | Slot size: ``uint`` | | Application MCU bootable: | +| | | | | | | +| | (``-1`` indicates no booting capability) | | | | ``MEM/2/0xeff8000/0x10000`` | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| ``CAND_MFST`` | ID: ``uint`` | | | | ``CAND_MFST/0`` | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| ``CAND_IMG`` | ID: ``uint`` | | | | ``CAND_IMG/0`` | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| ``INSTLD_MFST`` | Manifest Class ID: ``bst`` | | | | ``INSTLD_MFST/0x3f6a3a4dcdfa58c5accef9f584c41124`` | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| ``SOC_SPEC`` | ID: ``uint`` | | | | nRF54H20: | +| | | | | | | +| | Identifier valid within the namespace of a specific | | | | ``SOC_SPEC/1`` - SDFW | +| | SOC. | | | | | +| | | | | | ``SOC_SPEC/2`` - SDFW_Recovery | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ +| ``CACHE_POOL`` | ID: ``uint`` | | | | ``CACHE_POOL`` in DFU Partition (MRAM): | +| | | | | | | +| | | | | | ``CACHE_POOL/0`` | ++----------------------+--------------------------------------------------------+------------------------+------------------------+--------------+----------------------------------------------------------------------------------+ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_dfu.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_dfu.rst new file mode 100644 index 00000000000..a5306b89f51 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_dfu.rst @@ -0,0 +1,562 @@ +:orphan: + +.. _ug_nrf54h20_suit_customize_dfu: + +How to customize the SUIT DFU process +##################################### + +.. contents:: + :local: + :depth: 2 + +Nordic Semiconductor provides a Software Update Internet of Things (SUIT) sample (```nrf54h_suit_sample``) which uses predefined configurations in the build system. +The specified Kconfig options in the sample can be used to customize the DFU process and integrate the DFU solution with external build systems. +This guide provides a comprehensive set of instructions for modifying values in the :ref:`SUIT manifest `. + +Overview of the SUIT DFU procedure +********************************** + +The SUIT DFU protocol is essential for secure, reliable firmware updates in IoT devices, particularly for the nRF54H20 SoC. +It consists of two main concepts: the SUIT envelope and the SUIT manifest. + +* The SUIT envelope acts as a secure container for transporting firmware updates, encapsulating the firmware binary and its manifest. +* The SUIT manifest is a structured file with metadata essential for the update process, including firmware version, size, and hash for integrity verification. + +During the first build of the ``nrf54h_suit_sample``, default manifest templates are provided. +These templates form the basis for generating SUIT envelopes and manifests tailored to specific application requirements. +Customization of these templates is crucial for specific use cases and security requirements. + +For detailed guidance on customizing these templates, refer to the :ref:`ug_suit_modify_manifest_temps` section. + +.. figure:: images/nrf54h20_suit_dfu_overview.png + :alt: Overview of the SUIT DFU procedure + + Overview of the SUIT DFU procedure + +Requirements +************ + +For this user guide, the following development kit is required: + ++------------------------+----------+--------------------------------+-------------------------------+ +| **Hardware platforms** | **PCA** | **Board name** | **Build target** | ++========================+==========+================================+===============================+ +| nRF54H20 DK | PCA10175 | ``nrf54h20dk_nrf54h20_cpuapp`` | ``nrf54h20dk_nrf54h20_cpuapp``| ++------------------------+----------+--------------------------------+-------------------------------+ + +Software requirements +--------------------- + +This guide requires the following software: + +* Toolchain Manager - For installing the full |NCS| toolchain. +* Microsoft's |VSC| - The recommended IDE for |NCS|. +* |nRFVSC| - An add-on for |VSC| for developing |NCS| applications. +* nRF Command Line Tools - Mandatory tools for working with |NCS|. +* **suit-generator** - A Python package by Nordic Semiconductor for generating SUIT envelopes and manifests. + +Download instructions are in the README file `here `__. + +.. _ug_suit_build_system_config: + +Build system configuration +************************** + +The build system generates SUIT envelopes using predefined manifest templates provided by Nordic Semiconductor. +These templates, suitable for standard development needs, are automatically placed in the sample directory after the first build. +Customizing UUIDs in the manifest templates enhances security and is recommended for specific use cases. +For information about adding custom UUID values, refer to the :ref:`ug_suit_using_manifest_gen` section. + +After the first build of the ``nrf54h_suit_sample``, three additional files are created in the :file:`nrf/samples/suit/smp_transfer` directory (or two levels above the build directory when using the ``west -d`` parameter): + +* Root manifest - :file:`root_hierarchical_envelope.yaml.jinja2` +* Application Domain manifest - :file:`app_envelope.yaml.jinja2` +* Radio Domain manifest - :file:`rad_envelope.yaml.jinja2` + +The destination directory for these :file:`jinja2` file templates can be changed by setting the :kconfig:option:`CONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION` Kconfig option. + +.. note:: + The Radio Domain manifest template is available only for the Bluetooth® Low Energy version of the ``nrf54h_suit_sample``, not the UART version. + +.. _ug_suit_change_manifest_location: + +How to change the location of the manifest templates +---------------------------------------------------- + +Let us assume that you would like to store the editable manifest templates in the ``C:\my_templates\`` directory for a Windows machine, or in ``/home/my_user/my_templates`` for Linux. + +.. tabs:: + + .. group-tab:: Windows + + Enter the following command to change the location where the editable manifest templates are stored: + + .. code-block:: console + + west build -d C:/ncs-lcs/work_dir/build/ -b nrf54h20dk_nrf54h20_cpuapp -p -- -DCONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION="C:/my_templates" + + .. group-tab:: Linux + + Enter the following command to change the location where the editable manifest templates are stored: + + .. code-block:: console + + west build -b nrf54h20dk_nrf54h20_cpuapp -p -- -DCONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION="/home/my_user/my_templates" + +The source of the manifest templates can be configured by setting the following Kconfig options: + +* :kconfig:option:`CONFIG_SUIT_ENVELOPE_ROOT_TEMPLATE` + +* :kconfig:option:`CONFIG_SUIT_ENVELOPE_APP_TEMPLATE` + +* :kconfig:option:`CONFIG_SUIT_ENVELOPE_HCI_RPMSG_SUBIMAGE_TEMPLATE` + +Changing the source of manifest templates allows you to create manifest files on your own, without relying on the templates provided by Nordic Semiconductor. + +.. _ug_suit_use_own_manifest: + +How to use your own manifest +---------------------------- + +Let us analyze the case where you would like to: + +* Use your own created manifest template + +* Store editable manifest templates in a custom directory + +.. tabs:: + + .. group-tab:: Windows + + The provided manifest templates are stored in ``C:\my_default_templates``. + Editable manifests should be stored in ``C:\my_templates``. + + .. group-tab:: Linux + + The provided manifest templates are stored in ``/home/my_user/my_default_templates``. + Editable manifests should be stored in ``/home/my_user/my_templates``. + +The following files should be used to create DFU envelope: + +* Root envelope - :file:`root.yaml.jinja2` + +* Application Domain - :file:`app.yaml.jinja2` + +* Radio Domain - :file:`radio.yaml.jinja2` + +.. figure:: images/nrf54h20_suit_example_update_process.png + :alt: Example update process + + Example update process + +To build the described example with the provided manifest templates taken from your customized source folder, and to store it in your customized destination folder: + +.. tabs:: + + .. group-tab:: Windows + + Run the following command: + + .. code-block:: console + + west build -d C:/ncs-lcs/work_dir/build/ -b nrf54h20dk_nrf54h20_cpuapp -p -- -DCONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION="c:/my_templates" -DCONFIG_SUIT_ENVELOPE_ROOT_TEMPLATE="c:/my_default_templates/root.yaml.jinja2" -DCONFIG_SUIT_ENVELOPE_APP_TEMPLATE="c:/my_default_templates/app.yaml.jinja2" -DCONFIG_SUIT_ENVELOPE_HCI_RPMSG_SUBIMAGE_TEMPLATE="c:/my_default_templates/radio.yaml.jinja2" + + .. group-tab:: Linux + + Run the following command: + + .. code-block:: console + + west build -b nrf54h20dk_nrf54h20_cpuapp -p -- -DCONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION="/home/my_user/my_templates" -DCONFIG_SUIT_ENVELOPE_ROOT_TEMPLATE="/home/my_user/my_default_templates/root.yaml.jinja2" -DCONFIG_SUIT_ENVELOPE_APP_TEMPLATE="/home/my_user/my_default_templates/app.yaml.jinja2" -DCONFIG_SUIT_ENVELOPE_HCI_RPMSG_SUBIMAGE_TEMPLATE="/home/my_user/my_default_templates/radio.yaml.jinja2" + +Editable manifest copied into the sample directory (or in the directory configured using the :kconfig:option:`CONFIG_SUIT_ENVELOPE_EDITABLE_TEMPLATES_LOCATION` Kconfig option) can be modified to edit the contents of the envelopes and modify the DFU process. +These files will not be overwritten by the build system during the next builds or in consecutive SDK releases. + +For more information about the Kconfig options used in this example, see the `SUIT Kconfig options `__. + +.. _ug_suit_modify_manifest_temps: + +Modify the manifest templates +***************************** + +Customizing the manifest templates is recommended, especially the values for ``class-identifier`` and ``vendor-identifier``. +These templates are rendered to YAML files representing the output binary SUIT envelopes. + +The whole process of building a DFU envelope (which contains the manifests) can be summarized with the following diagram: + +.. figure:: images/nrf54h20_suit_generator_workflow.png + :alt: Modifying manifest templates workflow + + Modifying manifest templates workflow + +Manifest templates (``.jinja2``) files are rendered to YAML files. +These YAML files are used as a representation of the output binary SUIT envelopes. +The provided manifest templates (``.jinja2``) files contain variables (represented as components), such as memory ranges, names, and paths to binaries. +The component values are filled out automatically by the build system during the manifest rendering. + +Variables in the provided templates, like memory ranges and paths to binaries, are filled out by the build system. +However, values like ``class-identifier`` and ``vendor-identifier`` should be customized manually. + +An example of a YAML representation for a basic installation and invoke-process of the Application firmware could look like the following: + +.. code-block:: + + SUIT_Envelope_Tagged: + suit-authentication-wrapper: + SuitDigest: + suit-digest-algorithm-id: cose-alg-sha-256 + suit-manifest: + suit-manifest-version: 1 + suit-manifest-sequence-number: 1 + suit-common: + suit-components: + - - MEM + - 0x02 + - 0x0E0AA000 + - 0x0007f800 + suit-shared-sequence: + - suit-directive-override-parameters: + suit-parameter-vendor-identifier: + RFC4122_UUID: nordicsemi.com # Vendor identifier value + suit-parameter-class-identifier: + RFC4122_UUID: # Class identifier values + namespace: nordicsemi.com + name: nRF54H20_sample_app + suit-parameter-image-digest: + suit-digest-algorithm-id: cose-alg-sha-256 + suit-digest-bytes: + file: ``/path/to/application_fw.bin`` + suit-parameter-image-size: + file: ``/path/to/application_fw.bin`` + - suit-condition-vendor-identifier: + - suit-send-record-success + - suit-send-record-failure + - suit-send-sysinfo-success + - suit-send-sysinfo-failure + - suit-condition-class-identifier: + - suit-send-record-success + - suit-send-record-failure + - suit-send-sysinfo-success + - suit-send-sysinfo-failure + suit-install: + - suit-directive-override-parameters: + suit-parameter-uri: '#app' + - suit-directive-fetch: + - suit-send-record-failure + suit-integrated-payloads: + '#app': ``/path/to/application_fw.bin`` + +.. note:: + Default values of OEM-controlled manifests (related to the Application and Radio Domains) are hardcoded in the SDFW, but you can overwrite these values and this is strongly recommended. + +The ``class-identifier`` and ``vendor-identifier`` values in the manifest templates, like :file:`app_envelope_yam.jinja2`, can be modified to suit specific requirements. +For example, changing these values from `nordicsemi.com` to a custom vendor or class identifier enhances the specificity and security of the DFU process. + +Before modification: + +.. code-block:: + + - suit-directive-override-parameters: + suit-parameter-vendor-identifier: + RFC4122_UUID: nordicsemi.com # Original vendor-identifier value + suit-parameter-class-identifier: + RFC4122_UUID: + namespace: nordicsemi.com # Original class-identifier values + name: nRF54H20_sample_app + +After modification: + +.. code-block:: + + - suit-directive-override-parameters: + suit-parameter-vendor-identifier: + RFC4122_UUID: ACME Corp # Changed vendor-identifier value + suit-parameter-class-identifier: + RFC4122_UUID: # Changed class-identifier values + namespace: ACME Corp + name: Light bulb + +Python to generate UUIDs +------------------------ + +Note that the UUID raw values in the previous example have been calculated using following Python commands: + +.. code-block:: python + + from uuid import uuid5 + vid = uuid5(uuid.NAMESPACE_DNS, 'ACME Corp') + print(vid) # Result being bf42bd2ea9895f22933b352cda1730d3 + cid = uuid5(vid, 'Light bulb') + print(cid) # Result being e0f94076c46a5a1e80a18d3e674bdfe0 + +For more information on customizable variables and methods available in the manifest templates, see the :ref:`ug_suit_var_methods_in_manifest` section. + +.. _ug_suit_var_methods_in_manifest: + +Variables and methods available in the manifest templates +********************************************************** + +The manifest templates have access to the following: + +* Devicetree values (`edtlib object `__) + +* Target names + +* Paths to binary artifacts + +* Application version + +Some of these values are stored in the Python dictionaries that are named after the target name. +(Therefore, Python is used within the ``.jinja2`` files to fill in the necessary values in the manifest(s).) +For example, for the ``nrf54h_suit_sample`` there will be two variables available: ``app`` and ``hci_rpmsg_subimage``. +Each variable is a Python dictionary type (``dict``) containing the following keys: + +* ``name`` - name of the target + +* ``dt`` - Devicetree representation (`edtlib object `__) + +* ``binary`` - path to the binary, which holds the firmware for the target + +Additionally, the Python dictionary holds a variable called ``version`` that holds the application version. +With the Python dictionary you are able to, for example: + +* Extract the CPU ID by using ``app['dt'].label2node['cpu'].unit_addr`` + +* Obtain the partition address with ``app['dt'].chosen_nodes['zephyr,code-partition']`` + +* Obtain the size of partition with ``app['dt'].chosen_nodes['zephyr,code-partition'].regs[0].size`` + +* Get the pair of URI name and the binary path by using ``'#{{ app['name'] }}': {{ app['binary'] }}`` + +* Get the application version with ``suit-manifest-sequence-number: {{ version }}`` + +Additionally, the **get_absolute_address** method is available to recalculate the absolute address of the partition. +With these variables and methods, you can define templates which will next be filled out by the build system and use them to prepare the output binary SUIT envelope. +The examples below demonstrate the use of these variables and methods. + +.. _ug_suit_suit_set_comp_def_mem_range: + +Set component definition and memory ranges +------------------------------------------ + +In the :file:`app_envelope_yaml.jinja2` (found `here `__), the component definition and memory ranges are filled out by using the ``edtlib`` object like so: + +.. code-block:: + + suit-components: + - - MEM + - ``{{ app['dt'].label2node['cpu'].unit_addr }}`` + - ``{{ get_absolute_address(app['dt'].chosen_nodes['zephyr,code-partition']) }}`` + - ``{{ app['dt'].chosen_nodes['zephyr,code-partition'].regs[0].size }}`` + +.. note:: + See the :ref:`ug_suit_dfu_component_def` page for a full list and table of the available customizable components. + +Set integrated payload +---------------------- + +In the :file:`app_envelope_yaml.jinja2` (found `here `__, the integrated payload definition is done using the target name and binary location: + +.. code-block:: + + suit-integrated-payloads: + ``'#{{ app['name'] }}': {{ app['binary'] }}`` + +.. _ug_suit_root_manifest_temp: + +Root manifest template +---------------------- + +The :file:`root_hierarchical_envelope.yaml.jinja2` (found `here `__) contains content that is dynamically created, depending on how many targets are built. +The following example only shows a selected portion of the root manifest file. +For more information, see the file available in the sample and `Jinja `__ documentation: + +.. code-block:: + + {%- set component_index = 0 %} # Initialize the `component_index variable`. + # This variable will be used to assign component indexes dynamically depending on + # how many cores have been built. + + + {%- set component_list = [] %} # Initialize the `component_list variable`. + # This variable will be used to execute `suit-directive-set-component-index` over + # all components, except the first one with index 0. + + SUIT_Envelope_Tagged: + suit-authentication-wrapper: + SuitDigest: + suit-digest-algorithm-id: cose-alg-sha-256 + suit-manifest: + suit-manifest-version: 1 + suit-manifest-sequence-number: {{ version }} # Assign value defined in the `CONFIG_APP_VERSION` Kconfig option. + suit-common: + suit-components: + - - CAND_MFST + - 0 + {%- if hci_rpmsg_subimage is defined %} # Add section below only, in case the Radio Core has been already been built. + {%- set component_index = component_index + 1 %} # Increment `component_index`. + {%- set hci_rpmsg_subimage_component_index = component_index %} # Store the current component index for further use. + {{- component_list.append( hci_rpmsg_subimage_component_index ) or ""}} # Append the current component index to the common list. + - - INSTLD_MFST + - RFC4122_UUID: + namespace: nordicsemi.com + name: nRF54H20_sample_rad + {%- endif %} + {%- if app is defined %} + {%- set component_index = component_index + 1 %} + {%- set app_component_index = component_index %} + {{- component_list.append( app_component_index ) or ""}} + - - INSTLD_MFST + - RFC4122_UUID: + namespace: nordicsemi.com + name: nRF54H20_sample_app + {%- endif %} + +.. _ug_suit_ref_for_edit_manifest: + +Reference for editing manifest values +------------------------------------- + +Some entries in the YAML file will filled in automatically, (upon first build of the sample) by the build system in the final binary DFU envelope. + ++---------------------------------------------------------+------------------------------+------------------------------------------------+ +| Operation | YAML entry | Value in the output binary envelope | ++=========================================================+==============================+================================================+ +| UUID calculation | RFC4122_UUID: | ``3f6a3a4dcdfa58c5accef9f584c41124`` | +| | namespace: | | +| | nordicsemi.com | | +| | name: | | +| | nRF54H20_sample_root | | ++---------------------------------------------------------+------------------------------+------------------------------------------------+ +| Digest calculation for provided file | suit-digest-bytes: | ```` | +| | file: app.bin | | ++---------------------------------------------------------+------------------------------+------------------------------------------------+ +| Image size calculation for provided file | suit-parameter-image-size: | ```` | +| | file: app.bin | | ++---------------------------------------------------------+------------------------------+------------------------------------------------+ +| Attaching data to the envelope as an integrated payload | suit-integrated-payloads: | ```` | +| | '#application': | | +| | app.bin | | ++---------------------------------------------------------+------------------------------+------------------------------------------------+ + +For more information, see the example YAML files available in the `suit-generator repository `__. + +.. _ug_suit_using_manifest_gen: + +How to use the manifest generator +********************************** + +The **suit-generator** tool is used by the build system to create and parse SUIT envelopes. +This Python-powered tool can be used as a command-line application, a Python module, or a script. + +To use **suit_generator** from the command line: + +.. code-block:: + + pip install /modules/lib/suit-generator + suit-generator --help + suit-generator create --input-file input.yaml --output-file envelope.suit + suit-generator parse --input-file envelope.suit + +As a Python module: + +.. code-block:: python + + from suit_generator import envelope + envelope = SuitEnvelope() + envelope.load('input.yaml') + envelope.dump('output.suit') + +Executing the Python script from the command line: + +.. code-block:: + + python /modules/lib/suit-generator/cli.py create --input-file input.yaml --output-file envelope.suit + +.. _ug_suit_edit_build_artifacts: + +Edit build artifacts +-------------------- + +The ``nrf54h_suit_sample`` :file:`/build` directory contains several artifacts related to the SUIT process: + +* :file:`./build/hci_rpmsg/zephyr/hci_rpmsg_subimage.yaml` +* :file:`./build/zephyr/app.yaml` +* :file:`./build/zephyr/root.yaml` +* :file:`./build/hci_rpmsg/zephyr/hci_rpmsg_subimage.suit` +* :file:`./build/zephyr/app.suit` +* :file:`./build/zephyr/root.suit` + +These files can be used with the **suit-generator** for various purposes, such as recreating SUIT files, restoring YAML files from a binary SUIT envelope, debugging a SUIT envelope, and converting between different SUIT-related file types. + +.. note:: + You must build the sample at least once to make these artifacts available. + +Recreate SUIT files +------------------- + +To recreate SUIT files: + +.. code-block:: + + suit-generator create --input-file ./build/zephyr/root.yaml --output-file my_new_root.suit + +Restore YAML files from a binary SUIT envelope +---------------------------------------------- + +To restore a YAML file from a binary SUIT envelope: + +.. code-block:: + + suit-generator parse --input-file ./build/zephyr/root.suit --output-file my_new_root.yaml + +Debug a SUIT envelope +--------------------- + +To debug the a SUIT envelope, by printing their parsed content to the ``stdout``, run the following: + +.. code-block:: + + suit-generator parse --input-file ./build/zephyr/root.suit + +.. note:: + The previous command can be extended by parsing the dependent manifests by calling: + + .. code-block:: + + suit-generator parse --input-file ./build/zephyr/root.suit --parse-hierarchy + +Convert between file types +-------------------------- + +All mentioned artifacts can be converted back-and-forth, remembering that calculated and resolved YAML entries like UUIDs or files will be presented as a RAW value in the form of HEX strings. + +For example, if you have an input entry like the following: + +.. code-block:: + + suit-parameter-class-identifier: + RFC4122_UUID: + namespace: nordicsemi.com + name: nRF54H20_sample_app + +This entry will be presented, after parsing, as the following: + +.. code-block:: + + suit-parameter-class-identifier: + raw: 08c1b59955e85fbc9e767bc29ce1b04d + +Reference for suit-generator +**************************** + +Find more information about the **suit-generator** in the `README.md `__ file and its documentation. + +To build the **suit-generator** documentation: + +.. code-block:: + + cd /modules/lib/suit-generator + pip install ./ + pip install -r doc/requirements-doc.txt + sphinx-build -b html doc/source/ doc/build/html diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_qsg.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_qsg.rst new file mode 100644 index 00000000000..4099633bc4f --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_customize_qsg.rst @@ -0,0 +1,123 @@ +:orphan: + +.. _ug_nrf54h20_suit_customize_dfu_qsg: + +Customize SUIT DFU quick start guide +#################################### + +.. contents:: + :local: + :depth: 2 + +This quick start guide explains how to customize the Software Update for Internet of Things (SUIT) Device Firmware Update (DFU) to target your specific nRF54H20 System-on-Chip (SoC). +It is aimed at users new to the SUIT DFU process. + +Overview +******** + +The following are basic SUIT concepts you need to understand to be able to customize SUIT DFU for your device: + +* SUIT uses envelopes that serve as a secure transport container, and the SUIT manifest contains crucial deployment metadata. + +* SUIT envelopes are generated from manifest templates. + +* The SUIT manifest is like a blueprint that tells the system how to create a SUIT envelope, and contains instructions and metadata for the DFU procedure. + +* Default SUIT manifest templates are provided, but customization, especially for UUIDs, is recommended. + +* The manifest templates are automatically created and copied to the sample directory on the first build of SUIT samples. + +.. figure:: images/nrf54h20_suit_dfu_overview.png + :alt: Overview of the SUIT DFU procedure + + Overview of the SUIT DFU procedure + +See the :ref:`ug_nrf54h20_suit_intro` for more information about SUIT-specific concepts. + +SUIT DFU process +================ + +The SUIT DFU process involves creating a SUIT envelope, which includes a manifest outlining the steps for the update. +When you first build the SUIT sample in the |NCS|, you receive default manifest templates which you can customize according to your project's requirements. +This guide will walk you through how to customize the SUIT manifest to target your specific device. + +For a complete guide on all customizable aspects of the SUIT DFU procedure, see the :ref:`ug_nrf54h20_suit_customize_dfu` user guide. + +Detailed reading +================ + +If you want to learn more about SUIT DFU topics and terminology mentioned in this guide, read the following pages: + +* :ref:`ug_nrf54h20_suit_intro` page to learn more about SUIT-specific concepts, and an overview of the SUIT DFU procedure +* :ref:`ug_nrf54h20_suit_manifest_overview` page for more information on how the SUIT manifest works +* :ref:`ug_nrf54h20_suit_hierarchical_manifests` to learn more about the structure of the SUIT manifests implemented by Nordic Semiconductor +* :ref:`ug_nrf54h20_suit_why` to learn why SUIT was selected as the DFU procedure for the nRF54H Series devices + +Requirements +************ + +For this quick start guide, you need the following development kit: + ++------------------------+----------+--------------------------------+-------------------------------+ +| **Hardware platforms** | **PCA** | **Board name** | **Build target** | ++========================+==========+================================+===============================+ +| nRF54H20 DK | PCA10175 | ``nrf54h20dk_nrf54h20_cpuapp`` | ``nrf54h20dk_nrf54h20_cpuapp``| ++------------------------+----------+--------------------------------+-------------------------------+ + +Software requirements +===================== + +For this quick start guide, we will install the following software: + +* Toolchain Manager - An application for installing the full |NCS| toolchain. +* Microsoft's |VSC| - The recommended IDE for the |NCS|. +* |nRFVSC| - An add-on for |VSC| that allows you to develop applications for the |NCS|. +* nRF Command Line Tools - A set of mandatory tools for working with the |NCS|. +* Any additional requirements described in the ``nrf54h_suit_sample` sample``. + +Building the SUIT sample +************************ + +Start by building the SUIT sample: + +.. code-block:: console + + west build -b nrf54h20dk_nrf54h20_cpuapp nrf/samples/suit/smp_transfer + +This command builds the SUIT sample for the nRF54H20 SoC. + +Modifying class and vendor identifiers +************************************** + +The next step involves customizing identifiers in the manifest: + +1. Open the manifest template file located at `nrf/samples/suit/smp_transfer/app_envelope.yaml.jinja2`. +#. Find the ``class-identifier`` and ``vendor-identifier`` entries in the :file:`.yaml.jinja2` file. +#. Replace default values with unique identifiers for your application, like so: + +.. code-block:: + + - suit-directive-override-parameters: + suit-parameter-vendor-identifier: + RFC4122_UUID: ACME Corp # Changed vendor-identifier value + suit-parameter-class-identifier: + RFC4122_UUID: # Changed class-identifier values + namespace: ACME Corp + name: Light bulb + +.. note:: + Replacing and using the correct UUIDs prevent conflicts in the DFU process. + +With the sample built and identifiers customized, your SUIT DFU process is now specifically configured for your nRF54H20 SoC. + +Next steps +********** + +The SUIT DFU procedure can further be customized by: + +* Creating and modifying your own manifests +* Generating raw UUID values +* Changing the default location of the manifests + +Instructions for these actions and further customization are described in the :ref:`ug_nrf54h20_suit_customize_dfu`. +Additionally, you can modify SUIT components within the manifest (see the :ref:`ug_nrf54h20_suit_components` page for more information). diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_dfu.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_dfu.rst new file mode 100644 index 00000000000..a5fd4a4bc10 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_dfu.rst @@ -0,0 +1,32 @@ +:orphan: + +.. _ug_nrf54h20_suit_dfu: + +Device Firmware Update using SUIT +################################# + +.. contents:: + :local: + :depth: 2 + +The Software Updates for Internet of Things (SUIT) is the Device Firmware Upgrade (DFU) and secure boot method for nRF54H Series of System-on-Chip. +The SUIT procedure features a script-based system that resides in a :ref:`SUIT manifest `. +The manifest contains instructions for the DFU and booting procedure, and can be customized. +It includes the use of :ref:`sequences ` (conditions and directives) as well as the concept of :ref:`components `. + +To use the SUIT DFU in a product you need to customize it. +You can learn about this in the :ref:`ug_nrf54h20_suit_customize_dfu` page, which involves using the ``nrf54h_suit_sample`` sample. + + +.. toctree:: + :maxdepth: 2 + :caption: Subpages: + + ug_nrf54h20_suit_customize_qsg.rst + ug_nrf54h20_suit_customize_dfu.rst + ug_nrf54h20_suit_intro.rst + ug_nrf54h20_suit_manifest_overview.rst + ug_nrf54h20_suit_components.rst + ug_nrf54h20_suit_hierarchical_manifests.rst + ug_nrf54h20_suit_why.rst + ug_nrf54h20_suit_compare_other_dfu.rst diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_hierarchical_manifests.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_hierarchical_manifests.rst new file mode 100644 index 00000000000..ea941c7bb93 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_hierarchical_manifests.rst @@ -0,0 +1,70 @@ +:orphan: + +.. _ug_nrf54h20_suit_hierarchical_manifests: + +Hierarchical manifests +###################### + +.. contents:: + :local: + :depth: 2 + +The Software Updates for the Internet of Things (SUIT) procedure provides the option to employ a hierarchical manifest system. +In theory the SUIT SFU procedure could be executed with a single manifest however, this approach could lead to certain limitations. +Having multiple, unrelated manifest in the system raises the risk of system inconsistency. +To mitigate this risk, a specific manifest hierarchy has been introduced. + +Additionally, splitting the system into more than one part (each described by a separated manifest) allows for: + +* Assigning different signing authorities per system parts, (a single part is represented by a single SUIT manifest). + +* Assigning different access rights to certain memory locations on the device. + (Due to security reasons, the manifest representing the Radio Domain is not be able to install, alter, read-out images or memory locations assigned to the Application Domain.) + +* Possibility to assign different downgrade prevention or signing verification policies per single domain. + +Manifest topology +***************** + +Manifest are organized in a hierarchy-tree structure consisting of a single root manifest and several dependency manifests: + +.. figure:: images/nrf54h20_suit_manifest_topology.png + :alt: Hierarchical manifest topology + + Hierarchical manifest topology + +Default manifest topology for the nRF54H20 SoC +********************************************** + +The following image shows the default manifest topology for the nRF54H20 SoC: + +.. figure:: images/nrf54h20_suit_default_manifest_topology.png + :alt: Default manifest topology for the nRF54H20 SoC + + Default manifest topology for the nRF54H20 SoC + +Manifest located in the lowest positions of the hierarchy (such as the Application Local, Radio Local, System Controller, SDFW, and SDFW_Recovery manifests) contain a specific updatable image for a specific core/domain of the device. +The Nordic Top manifest coordinates update and invocation logic for its dependencies (System Controller and SDFW). +The root manifest bundles all other manifests together and coordinates the entire DFU process. + +By default, using SUIT’s hierarchical manifest involves using your own generated manifests (OEM-controlled) in combination with manifests provided by Nordic Semiconductor (particularly for the Secure Domain (SecDom) and System Controller). +An example of how this would be implemented includes: + +* OEM-controlled manifests + + * A root manifest that coordinates update and invocation processes on its dependency manifests. + It does not belong to any domain or control any local domain resources. + + * A dependency manifest for each of the domains, such as the Application and Radio Domains. + +* Nordic Semiconductor controlled manifests - for the SecDom, including the System Controller. + They will be released by Nordic Semiconductor and can be incorporated into the firmware update package prepared by the OEM. + +To perform a DFU procedure on the nRF54H20 SoC, you can use manifest templates provided by Nordic Semiconductor and the **suit-generator** to create an update package. +See the :ref:`ug_nrf54h20_suit_customize_dfu` user guide for instructions and example use cases. + +If the manifest templates provided by Nordic Semiconductor do not address your specific needs, you can modify them. +Read the :ref:`ug_suit_modify_manifest_temps` section of the :ref:`ug_nrf54h20_suit_customize_dfu` user guide for instructions. + +Alternatively, you can use the manifest generator (**suit-generator**) to create your own manifests from scratch. +See the :ref:`ug_suit_use_own_manifest` section of the :ref:`ug_nrf54h20_suit_customize_dfu` user guide for instructions. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_intro.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_intro.rst new file mode 100644 index 00000000000..ca2ee4af407 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_intro.rst @@ -0,0 +1,226 @@ +:orphan: + +.. _ug_nrf54h20_suit_intro: + +Introduction to SUIT +#################### + +.. contents:: + :local: + :depth: 2 + +This documentives an overview of SUIT and its characteristics. +See the ``nrf54h_suit_sample`` if you want to try using the SUIT procedure on the nRF54H20 SoC. + +.. _ug_suit_overview: + +SUIT overview +************* + +SUIT uses a serialization format based on Concise Binary Object Representation (CBOR), and CBOR object signing and encryption (COSE) to ensure security. +The SUIT procedure features a flexible, script-based system that allows the DFU implementation to be customized, particularly for devices with multiple CPU cores. + +It also features a root manifest that contains the main instructions of the SUIT procedure, as well as local manifests for each of its required dependencies. +The SUIT manifests control the invocation procedure at the same level of detail as the update procedure. +See the :ref:`ug_nrf54h20_suit_manifest_overview` page to read more about the contents of the manifests. + +The nRF54H Series contains multiple CPUs with one dedicated CPU for the Secure Domain. +The Secure Domain CPU firmware is validated and started by the Secure Domain ROM. +When it starts execution, it continues the SoC boot sequence according to the manifest(s). +The local domain CPU firmware images are validated and started by the Secure Domain as instructed by the manifest. + +Once the invocation process is complete, the SDFW is still active and may serve specific requests from specified domains. +Therefore, unlike in MCUboot, the Application Core and other cores may use the SDFW services. +(See the :ref:`ug_nrf54h20_suit_compare_other_dfu` page for more details and further comparison of SUIT with other DFU and bootloader procedures.) +The bootloader SDFW image provided by Nordic Semiconductor is offered in binary form. +Along with this, you can compose a final image with your own application image that is signed by your own keys. + +.. figure:: images/nrf54h20_suit_example_update_workflow.png + :alt: Example of the anticipated workflow for an Application Domain update using SUIT + +.. _ug_suit_dfu_suit_concepts: + +SUIT-specific concepts +********************** + +Below is a description of SUIT-specific concepts. + +.. _ug_suit_dfu_component_def: + +Component +========= + +An updatable logical block of firmware, software, configuration, or data structure. +Components are the elements that SUIT operates on. +They are identified by the ``Component_ID`` in the manifest and are abstractions that map to memory locations on the device. +For example, a memory slot on a device that contains one firmware image is a typical example of a component, though components can be of any size. + +Command sequence +================ + +A set of commands. +Commands include both directives and conditions. +Most commands operate on components. + +Directive +--------- + +An action for the recipient device to perform. +For example, to copy code or a data payload from the source component to the specified destination. + +Condition +--------- + +A test that passes or fails for a specific property of the recipient device or its component(s). +For example, to ensure that the digest of the code or data in a specific component is equal to the expected value. + +Envelope +======== + +An outer container for the manifest that may also contain code or data payloads. +Code or data payloads are optional in the envelope because the manifest can be created so that payload fetching is encoded within the command sequences. + +The SUIT envelope includes: an authentication wrapper, the manifest, severable elements, integrated payloads, and the integrated dependencies. +Below is a description of the contents of the SUIT envelope structure that have not yet been described. + +Authentication wrapper +---------------------- + +Every SUIT envelope contains an authentication wrapper. +The wrapper contains cryptographic information that protects the manifest, and includes one or more authentication blocks. + +The authentication wrapper is important because it checks the authenticity of the manifest, but it is not involved in executing command sequences. + +.. figure:: images/nrf54h20_suit_envelope_structure.png + :alt: SUIT envelope structure + + SUIT envelope structure + +Manifest +-------- + +A bundle of metadata describing one or more pieces of code or data payloads. +This includes instructions on how to obtain those payloads, as well as how to install, verify, and invoke them. +These instructions are encoded in the manifest in the form of command sequences. +See the :ref:`ug_nrf54h20_suit_manifest_overview` page for more details about the contents of a manifest. +Each manifest, either the root or dependency manifest, is encased in its own envelope. + +.. note:: + + The manifest is the most important concept within SUIT. + The manifest is represented in a file, as either a YAML or JSON file based on Nordic Semiconductor's implementation, that can be edited to control aspects of the DFU. + +Severable elements +------------------ + +Severable elements are elements that belong to the manifest but are held outside of the manifest. +They can later be deleted when they are no longer needed to save storage space. +To maintain integrity, a digest of the severable element is kept inside the manifest. +These are optional for SUIT envelopes. + +Integrated payloads +------------------- + +Integrated payloads are payloads that are integrated within the envelope of the manifest. +This allows for a one-step update, where everything needed for the update is in one image (the envelope). +These are optional for SUIT envelopes. + +Integrated dependencies +----------------------- + +Integrated dependencies contain the manifests needed for any required dependencies and are encased in their own SUIT envelope structure. +These are optional for SUIT envelopes and only necessary if there are dependencies needed for the DFU. + +.. _ug_suit_dfu_suit_procedure: + +SUIT procedure +************** + +The SUIT procedure contains a SUIT envelope. +This envelope is a container to transport an update package. + +An update package contains an authentication wrapper, one root manifest within an envelope, severable elements, one or more payloads as well as integrated dependencies. +Payloads can be either: + +* Images + +* Dependency manifests (each in their own envelope) + +* Other data + +Payloads can be distributed individually or embedded in the envelope of the manifest where it is used. +This means that an update package or invocation process can be distributed in one large package or as several small packages. + +.. figure:: images/nrf54h20_suit_example_update_package.png + :alt: Example of an update package + + Example of an update package + +SUIT workflows +============== + +There are two anticipated workflows for the recipient device that is receiving the update: the update procedure and the invocation procedure. + +The update procedure contains the following steps: + +.. figure:: images/nrf54h20_suit_update_workflow.png + :alt: Update procedure workflow + + Update procedure workflow + +The invocation procedure contains the following steps: + +.. figure:: images/nrf54h20_suit_invocation_workflow.png + :alt: Invocation procedure workflow + + Invocation procedure workflow + +To follow these workflows, there are six main sequences in the SUIT procedure that belong to either the update or the invocation procedure. + +The update procedure has three sequences: + +* ``dependency-resolution`` - prepares the system for the update by identifying any missing dependency manifests. + +* ``payload-fetch`` - all non-integrated payloads are requested over the network. + +* ``install`` - the downloaded payloads are copied to their final location. + +The following is an example of `Diagnostic Notation `__ (decoded CBOR) that features the update procedure's ``payload-fetch``: + +.. code-block:: + + / payload-fetch / 16:<< [ + / directive-set-component-index / 12,1 , + / directive-override-parameters / 20,{ + / image-digest / 3:<< [ + / algorithm-id / -16 / "sha256" /, + / digest-bytes / h'0011…76543210' + + ] >>, + / uri / 21:'http://example.com/file.bin', + + } , + / directive-fetch / 21,2 , + / condition-image-match / 3,15 + ] >>, + + / install / 17:<< [ + / directive-set-component-index / 12,0 , + + / directive-override-parameters / 20,{ + / source-component / 22:1 / [h'02'] /, + + } , + / directive-copy / 22,2 , + / condition-image-match / 3,15 + ] >>, + + +The invocation procedure has three sequences, although not all of them are needed for every use case. +They are as follows: + +* ``validate`` - calculates the digest and checks that it matches the expected digest to ensure that a secure invocation process can take place. + +* ``load`` - is used in special cases when the firmware needs to be moved before invoking it. + +* ``invoke`` - hands over execution to the firmware. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_manifest_overview.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_manifest_overview.rst new file mode 100644 index 00000000000..5ff14bcb44e --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_manifest_overview.rst @@ -0,0 +1,190 @@ +:orphan: + +.. _ug_nrf54h20_suit_manifest_overview: + +SUIT manifest overview +###################### + +.. contents:: + :local: + :depth: 2 + +The SUIT DFU procedure features manifests, which are encased in a SUIT envelope. +The SUIT manifest contains components, which is the main element that the SUIT DFU procedure operates on. + +Out-of-the-box, Nordic Semiconductor's implementation of SUIT features a standard hierarchical manifest topology. +This includes the following: + +* A root manifest that contains the main execution instructions for the DFU within the different Domains. + +* Two local manifests, one for the Application Domain, another for the Radio Domain. + +* Manifests for the SecDom, which are controlled by Nordic Semiconductor and cannot be modified. + This includes a Nordic "Top" manifest, one specifically for the SecDom firmware (SDFW), and the System Controller. + +You can read more about manifest topology in the :ref:`ug_nrf54h20_suit_hierarchical_manifests` page. + +Manifest templates are provided by Nordic Semiconductor, and automatically generated when you build the ``nrf54h_suit_sample`` sample. +These templates work out-of-the-box for development and testing purposes. + +This document describes the contents of a SUIT manifest. +If you want to modify elements of the manifest template, see the :ref:`ug_nrf54h20_suit_customize_dfu` user guide. + +The ``SUIT_Manifest``, found within root and local manifests, contains several sequences. +These sequences are data structures that can contain directives and conditions. + +.. _ug_suit_dfu_suit_manifest_elements: + +Manifest elements +***************** + +``SUIT_Manifest`` contains contains metadata elements and command sequences (a kind of "scripts") within its structure. +These scripts contain the commands that will be executed at certain stages of the update process. +Additionally, they provide a shortcut when a component's information, or other data, needs to be repeated throughout the manifest. + +.. caution:: + + Sequences will be provided within the SUIT manifest templates for typical use cases. + These sequences can be customized, but with caution. + This is only recommended for advanced use cases. + +The SUIT manifest contains the following elements: + +``suit-manifest-version`` +========================= + +Checks and compares the version number of the manifest format, or, in other words, the serialization format. +If the SUIT processor receives a manifest and sees a version number it does not recognize, it will fail due to incompatibility. + +``suit-manifest-sequence-number`` +================================= + +This is a SUIT-specific version number of the software that is contained in this manifest. +It is compared against the existing sequence number to verify that the update is newer than the current software. +The sequence number does not have to match the official version number of the software, it only needs to increase for each update. + +.. _ug_suit_dfu_suit_common: + +``suit-common`` +=============== + +This element contains two subsections: + +* ``suit-components`` - a data field that contains all declared components to be targeted in the manifest. + + Components are identified by ``SUIT_Component_Identifier``, which is introduced by Nordic Semiconductor's implementation of the SUIT procedure. + For a list of available components, see the :ref:`ug_nrf54h20_suit_components` page. + +* ``suit-shared-sequence`` - a sequence that executes before the other sequences. + + It supports only a few directives and conditions. + + For example, when performing a DFU, the SUIT processor may be instructed to run ``suit-payload-fetch``, but first ``suit-shared-sequence`` runs before each sequence to save memory space. + This is done by declaring items, such as the vendor ID, in ``suit-shared-sequence`` once rather than declaring them separately for each update or invocation procedure. + +.. _ug_suit_dfu_suit_concepts_sequences: + +Sequences +********* + +SUIT manifest contains the following command sequences: + +* ``suit-payload-fetch`` - obtains the needed payloads. + +* ``suit-install`` - installs payloads. + + Typical actions may include: verifying a payload stored in temporary storage, coping a staged payload from temporary storage, and unpacking a payload. + +* ``suit-validate`` - validates that the state of the device is correct and okay for booting. + + Typically involves image validation. + +* ``suit-load`` - prepares payload(s) for execution. + + A typical action of this sequence is to copy an image from the permanent storage into the RAM. + +* ``suit-invoke`` - invokes (boots) image(s). + +* ``suit-dependency-resolution`` - prepares the system for the update by identifying and fetching any missing dependency manifests. + +.. _ug_suit_dfu_suit_directives: + +Directives +********** + +The SUIT procedure defines the following directives: + +* ``set-component-index`` - defines the component(s) to which successive directives and conditions will apply. + +* ``override-parameters`` - allows the manifest to configure the behavior of future directives or conditions by changing (as in, setting or modifying) parameters that are read by those directives or conditions. + +* ``fetch`` - retrieves the payload from a specified Uniform Resource Identifier (URI) and stores it in the destination component. + A URI is provided in the ``override-parameters`` directive. + The URI may indicate an external source, for example, HTTP or FTP, or the envelope (as a fragment-only reference as defined in `RFC3986 `__, such as ``"#app_image.bin"``). + +* ``copy`` - transfers the image from the source component to the destination component. + The source component is provided in the ``override-parameters`` directive. + +* ``write`` - works similarly to ``copy``, except that the source image is embedded in the manifest. + This directive is best for small blocks of data due to manifest size limitations. + +* ``invoke`` - starts the firmware. (In other words, "boots" the firmware.) + +* ``try-each`` - runs multiple ``SUIT_Command_Sequence`` instances, trying each one in succession. + It stops when one succeeds or continues to the next if one fails, making it valuable for handling alternative scenarios. + +* ``run-sequence`` - runs a single ``SUIT_Command_Sequence``. + +.. _ug_suit_dfu_suit_conditions: + +Conditions +********** + +The SUIT procedure defines the following conditions: + +* ``class-identifier``, ``vendor-identifier``, and ``device-identifier`` - these conditions make sure that the manifest procedure is working with the correct device. + The correct UUIDs (16 bytes) must be given. + + .. note:: + + Although not required, it is strongly recommended to change the values for ``class-identifier`` and ``vendor-identifier`` in the provided manifest templates. + Read the :ref:`ug_suit_modify_manifest_temps` section of the :ref:`ug_nrf54h20_suit_customize_dfu` user guide for instructions. + +* ``image-match`` - checks the digest of an image. + The expected digest and corresponding component are set here. + It goes into the component and calculates the digest of the component, then checks it against the expected digest. + +* ``component-slot`` - checks which component slot is currently active, if a component consists of multiple slots. + Slots are alternative locations for a component, where only one is considered "active" at one time. + + It also checks which component, or memory location, is unoccupied so you can download the new image to the unoccupied slot. + After reboot, the unoccupied component now has the new image, and the active image is not overridden. + This follows an A/B slot system. + +* ``check-content`` - a special case of image matching that matches directly with expected data, not a digest. + For use with small components where the overhead of digest checking is not wanted. Typically used when you want the manifest to check something other than the firmware. + + As opposed to ``image-match``, the specified component is checked against binary data that is embedded in the manifest with what is already installed in another component. + +* ``abort`` - if you want the procedure to fail. + +A sample description of ``SUIT_Manifest`` in CDDL is shown below. +Note that optional elements are preceded by a ``?``. +For more information about CDDL's syntax, see the IETF's `RFC 8610 `__. + +.. code:: + + SUIT_Manifest = { + suit-manifest-version => 1, + suit-manifest-sequence-number => uint, + suit-common => bstr .cbor SUIT_Common, + + ? suit-validate => bstr .cbor SUIT_Command_Sequence, + ? suit-load => bstr .cbor SUIT_Command_Sequence, + ? suit-invoke => bstr .cbor SUIT_Command_Sequence, + ? suit-payload-fetch => bstr .cbor SUIT_Command_Sequence, + ? suit-install => bstr .cbor SUIT_Command_Sequence, + ? suit-text => bstr .cbor SUIT_Text_Map + + * $$SUIT_Manifest_Extensions, + } diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_why.rst b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_why.rst new file mode 100644 index 00000000000..ab5426bfeb7 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54h/ug_nrf54h20_suit_why.rst @@ -0,0 +1,59 @@ +:orphan: + +.. _ug_nrf54h20_suit_why: + +Why SUIT was selected as a bootloader and DFU procedure +####################################################### + +.. contents:: + :local: + :depth: 2 + +The nRF54H Series contains multiple CPU cores and images as opposed to other products by Nordic Semiconductor, such as the nRF52 Series. +Multiple CPU cores add more possibilities for development and complexity for operations such as performing a DFU. +This requires a DFU procedure that can address the needs of a single device containing multiple cores and multiple images. + +Therefore, the SUIT procedure was selected due to its features: + +* Script-based systems that allow you to customize the instructions for installation and invocation + +* Dependency management between multiple executable images + +* Support for multiple signing authorities that will be required for each dependency + +* Customization for the allocation of upgradeable elements + +.. note:: + + The term "invocation" is used in this document to mean "booting procedure". + +Script-based systems +******************** + +SUIT features a script-based system. +This contains high-level instructions collected into *command sequences*. +SUIT's command sequences allow you to express certain sequences for installation and invocation in an imperative way. +This offers flexibility in cases where, for example, you want to minimize the size of a download within the DFU lifecycle to increase flash efficiency. + +This allows for extensive management of dependencies between components, meaning you can execute different logic on different groups of components. +For example, the location of a slot or component does not have to be static and can be changed within the manifest. + +The script-based system also allows you to direct the manifest to download only the necessary, specified data. +You can do this, for example, by checking what is already in the device receiving the DFU or by checking the version number of the existing firmware. +This saves on both transfer cost and memory on the device. + +SUIT topology +************* + +SUIT features a topology which allows for dependency management between multiple executable images. +Additionally, the SUIT topology allows you to provide multiple signing authorities that will be required for each dependency. + +For information on the SUIT topology used by Nordic Semiconductor's implementation of SUIT, see the :ref:`ug_nrf54h20_suit_hierarchical_manifests` page. + +Allocation of components +************************ + +SUIT itself does not decide the component allocation, rather it can be defined in the manifest. +This is because their location is flexible and there are some options available to change the location of a specific image within the manifest. + +See the :ref:`ug_nrf54h20_suit_compare_other_dfu` page for further information on why SUIT was selected for DFU procedures for the nRF54H Series of SoC. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15.svg b/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15.svg new file mode 100644 index 00000000000..9ad7397db6d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + nRF Connect SDK diagram + + + + + + Nordic Sky + nRF54L15 Application Core + + + + nRF54L15 Application Core + + Sheet.1 + Max 800 px + + + + + Max 800 px + + Sheet.2 + Max 780 px + + + + + Max 780 px + + Sheet.3 + + + + Sheet.4 + + + + Nordic Blueslate + Application + + + + Application + + Nordic Blue + Secure storage + + + + Secure storage + + Sheet.8 + Key management + + + + Key management + + Sheet.17 + Cryptography + + + + Cryptography + + Sheet.18 + Cryptographically Secure Pseudorandom Number Generator + + + + Cryptographically Secure Pseudorandom Number Generator + + Sheet.19 + Trusted Firmware-M + + + + Trusted Firmware-M + + Dynamic connector + + + + Sheet.39 + PSA Crypto API + + + + PSA Crypto API + + Dynamic connector.40 + + + + Sheet.41 + PSA Crypto API + + + + PSA Crypto API + + Nordic Middle Grey + Zephyr integration + + + + Zephyr integration + + Nordic Blue.26 + Multiprotocol Service Layer (MPSL) + + + + Multiprotocol Service Layer (MPSL) + + Nordic Blue.27 + Thread stack (OpenThread) + + + + Thread stack (OpenThread) + + Nordic Middle Grey.28 + Zephyr integration + + + + Zephyr integration + + Nordic Blue.29 + nRF IEEE 802.15.4 radio driver + + + + nRF IEEE 802.15.4radio driver + + Sheet.31 + IEEE 802.15.4 PHY + + + + IEEE 802.15.4 PHY + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15_multi.svg b/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15_multi.svg new file mode 100644 index 00000000000..822247aeb8d --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54l/images/thread_platform_design_nrf54l15_multi.svg @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + nRF Connect SDK diagram + + + + + + Nordic Sky + nRF54L15 Application Core + + + + nRF54L15 Application Core + + Sheet.1 + Max 800 px + + + + + Max 800 px + + Sheet.2 + Max 780 px + + + + + Max 780 px + + Sheet.3 + + + + Sheet.4 + + + + Nordic Blueslate + Application + Matter stack + + + + Application + Matter stack + + Nordic Blue + Secure storage + + + + Secure storage + + Sheet.8 + Key management + + + + Key management + + Sheet.17 + Cryptography + + + + Cryptography + + Sheet.18 + Cryptographically Secure Pseudorandom Number Generator + + + + Cryptographically Secure Pseudorandom Number Generator + + Sheet.19 + Trusted Firmware-M + + + + Trusted Firmware-M + + Nordic Blue.25 + Device Firmware Update + + + + Device Firmware Update + + Dynamic connector + + + + Sheet.39 + PSA Crypto API + + + + PSA Crypto API + + Dynamic connector.40 + + + + Sheet.41 + PSA Crypto API + + + + PSA Crypto API + + Nordic Middle Grey + Zephyr integration + + + + Zephyr integration + + Nordic Blue.26 + Multiprotocol Service Layer (MPSL) + + + + Multiprotocol Service Layer (MPSL) + + Nordic Blue.27 + Thread stack (OpenThread) + + + + Thread stack (OpenThread) + + Nordic Middle Grey.28 + Zephyr integration + + + + Zephyr integration + + Nordic Blue.29 + nRF IEEE 802.15.4 radio driver + + + + nRF IEEE 802.15.4radio driver + + Nordic Blue.30 + Bluetooth® LE stack + + + + Bluetooth® LE stack + + Sheet.31 + IEEE 802.15.4 PHY + + + + IEEE 802.15.4 PHY + + Sheet.32 + nRF Bluetooth® LE Controller + + + + nRF Bluetooth® LEController + + diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_gs.rst new file mode 100644 index 00000000000..dcc48814886 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_gs.rst @@ -0,0 +1,147 @@ +.. _ug_nrf54l15_gs: + +Getting started with the nRF54L15 PDK +##################################### + +.. contents:: + :local: + :depth: 2 + +This page will get you started with your nRF54L15 PDK using the |NCS|. +First, you need to install the required software and prepare the environment. +Once completed, test if your PDK is working correctly by running the preflashed :zephyr:code-sample:`blinky` sample. +The instructions will then guide you through how to configure, build, and program the :ref:`Hello World ` sample to the development kit, and how to read its logs. + +.. _ug_nrf54l15_gs_requirements: + +Minimum requirements +******************** + +Make sure you have all the required hardware and that your computer has one of the supported operating systems. + +Hardware +======== + +* nRF54L15 PDK + + .. note:: + + For commands, use the correct build target depending on your PDK version: + + * For the PDK revision v0.2.1, AB0-ES7, use the ``nrf54l15pdk_nrf54l15_cpuapp`` build target. + * For the PDK revision v0.3.0, use the ``nrf54l15pdk_nrf54l15_cpuapp@0.3.0`` build target. + +* USB-C cable + +Software +======== + +On your computer, one of the following operating systems: + +* macOS +* Microsoft Windows +* Ubuntu Linux + +|supported OS| +Make sure to install the v2.6.0 of :ref:`the nRF Connect SDK and the nRF Connect SDK toolchain `. +You also need to install `Git`_ or `Git for Windows`_ (on Linux and Mac, or Windows, respectively). + +Downloading the code +******************** + +Once you have installed the software, you need to update the code separately to be able to work with the nRF54L15 PDK. + +Go to the :file:`ncs/v2.6.0/nrf` folder and run the following commands: + +.. parsed-literal:: + :class: highlight + + git fetch + git checkout 8206081397428457926b075cfa67fdd4394fc067 + west update + +.. _ug_nrf54l15_gs_test_sample: + +Testing with the Blinky sample +****************************** + +The nRF54L15 PDK comes preprogrammed with the Blinky sample. + +Test if the PDK works correctly: + +1. Connect the USB-C end of the USB-C cable to the **IMCU USB** port the nRF54L15 PDK. +#. Connect the other end of the USB-C cable to your PC. +#. Move the **POWER** switch to **On** to turn the nRF54L15 PDK on. + +**LED1** will turn on and start to blink. + +If something does not work as expected, contact Nordic Semiconductor support. + +.. _ug_nrf54l15_gs_installing_software: + +Additional software +******************** + +You will need a :ref:`terminal emulator ` to program the sample and read the logs. +The recommended emulators are `nRF Connect Serial Terminal`_ or the nRF Terminal (part of the `nRF Connect for Visual Studio Code`_ extension). + +To make sure the device sees the environment, all the commands related to the |NCS|, building, and flashing need to be run from the nRF Connect terminal. + +.. _ug_nrf54l15_gs_sample: + +Programming the Hello World! sample +*********************************** + +The :ref:`zephyr:hello_world_user` Zephyr sample uses the ``nrf54l15pdk_nrf54l15_cpuapp`` build target. + +To build and program the sample to the nRF54L15 PDK, complete the following steps: + +1. Connect the nRF54L15 PDK to your computer using the IMCU USB port on the PDK. +#. Navigate to the :file:`zephyr/samples/hello_world` folder containing the sample. +#. Build the sample by running the following command: + + .. code-block:: console + + west build -b nrf54l15pdk_nrf54l15_cpuapp + +#. Program the sample by running the standard |NCS| command: + + .. code-block:: console + + west flash --erase + + If you have multiple Nordic Semiconductor devices, make sure that only the nRF54L15 PDK is connected. + + .. note:: + + When programming the device, you might get an error mentioning the readback protection of the device. + To get around the error, :ref:`program the device ` with the ``--recover`` parameter. + +.. _ug_nrf54l15_sample_reading_logs: + +Reading the logs +**************** + +With the :ref:`zephyr:hello_world_user` sample programmed, the nRF54L15 PDK outputs logs over UART 30. + +To read the logs from the :ref:`zephyr:hello_world_user` sample programmed to the nRF54L15 PDK, complete the following steps: + +1. Connect to the PDK with a terminal emulator (for example, `nRF Connect Serial Terminal`_) using the :ref:`default serial port connection settings `. +#. Press the **Reset** button on the PCB to reset the PDK. +#. Observe the console output: + + .. code-block:: console + + *** Booting Zephyr OS build 06af494ba663 *** + Hello world! nrf54l15dk_nrf54l15_cpuapp + + .. note:: + If no output is shown when using the nRF Serial Terminal, select a different serial port in the terminal application. + +Next steps +********** + +You have now completed getting started with the nRF54L15 PDK. +See the following links for where to go next: + +* :ref:`configuration_and_build` documentation to learn more about the |NCS| development environment. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_matter_thread.rst b/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_matter_thread.rst new file mode 100644 index 00000000000..b752e6361e5 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf54l/ug_nrf54l15_matter_thread.rst @@ -0,0 +1,158 @@ +:orphan: + +.. _ug_nrf54l15_matter_thread: + +Working with nRF54L15 and Matter and Thread +########################################### + +.. contents:: + :local: + :depth: 2 + +Starting with the ``v2.4.99-cs3`` limited customer sampling tag, the nRF54L15 PDK supports the following Matter and Thread samples: + +* :ref:`Matter template sample ` +* :ref:`Matter light bulb sample ` +* :ref:`Matter light switch sample ` +* :ref:`Matter window covering sample ` +* :ref:`Thread CLI sample ` +* :ref:`Thread coprocessor sample ` + +The Matter support is currently limited to Matter over Thread, and support for both Matter and Thread is currently :ref:`experimental `. +Read the following sections for more information about support in the nRF54L15 PDK and the platform design for the nRF54L15 SoC. + +For more information about Matter and Thread in the |NCS|, read the documentation in the :ref:`ug_matter` and :ref:`ug_thread` protocol sections. + +Platform designs for the nRF54L15 SoC +************************************* + +Matter in the |NCS| supports the *System-on-Chip, multiprotocol* platform design for the nRF54L15 SoC using Matter over Thread. +You can read more about other available platform designs for Matter on the :ref:`Matter platform design page`. + +Thread in the |NCS| supports the *System-on-Chip, single protocol* and *System-on-Chip, multiprotocol* platform designs for the nRF54L15 SoC. +You can read more about other available platform designs for Thread on the :ref:`OpenThread architectures page`. + +For more information about the multiprotocol feature, see :ref:`ug_multiprotocol_support`. + +System-on-Chip, single protocol +=============================== + +In this design, the OpenThread stack runs on single core of a single nRF54L15 SoC. + +This platform designs is suitable for the following development kit: + +.. TO DO: /includes/sample_board_rows.txt for nrf54l15dk_nrf54l15_cpuapp@soc1 to be added + +In this design the Application Core runs the OpenThread stack and the component that is related to the 802.15.4 IEEE Radio Driver. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented. + +The following figure demonstrates the architecture. + +.. _nrf54l15_platform_single_figure: + +.. figure:: images/thread_platform_design_nrf54l15.svg + :alt: Multiprotocol Thread and Bluetooth LE architecture (nRF54L15) + + Single protocol Thread architecture on the nRF54L15 SoC + +System-on-Chip, multiprotocol +============================= + +In this design, the OpenThread stack and the Bluetooth® Low Energy (LE) stack run on single core of a single nRF54L15 SoC. + +This platform design is suitable for the following development kit: + +.. TO DO: /includes/sample_board_rows.txt for nrf54l15dk_nrf54l15_cpuapp@soc1 to be added + +In this design the Application Core runs the OpenThread stack, the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver, and a part of the Bluetooth LE Controller. +Device Firmware Update component (DFU) is available only in the Matter solution. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented. + +The following figure demonstrates the architecture. + +.. _nrf54l15_platform_multi_figure: + +.. figure:: images/thread_platform_design_nrf54l15_multi.svg + :alt: Multiprotocol Thread and Bluetooth LE architecture (nRF54L15) + + Multiprotocol Thread and Bluetooth LE architecture on the nRF54L15 SoC + +Matter over Thread +================== + +In this design, the Matter stack, the OpenThread stack, and the Bluetooth LE stack run on single core of a single nRF54L15 SoC. + +This platform design is suitable for the following development kit: + +.. TO DO: /includes/sample_board_rows.txt for nrf54l15dk_nrf54l15_cpuapp@soc1 to be added + +In this design: + +* The Application Core runs the Matter stack, the OpenThread stack, the component of the OpenThread stack that is related to the 802.15.4 IEEE Radio Driver and a part of the Bluetooth LE Controller. + + .. note:: + The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. + +Refer to the :ref:`nrf54l15_platform_multi_figure` figure to see the architecture of the SoC. +The Global Domain is not included. + +Additional requirements on the nRF54L15 PDK +******************************************* + +In addition to the standard requirements for the |NCS|, such as the :ref:`ug_matter_gs_tools_gn` for Matter, you need the following to run Matter-enabled or Thread-enabled applications on the nRF54L15 PDK: + +* For DFU - J-Link and a USB cable. +* The compatible version of the nrfjprog tool, included in the nRF Command Line Tools. + +Configuring Matter and Thread on the nRF54L15 PDK +************************************************* + +Currently, only the configuration for Matter over Thread is supported for Matter. +Follow the configuration steps on the :ref:`ug_matter_gs_testing` page to configure the Matter environment for the supported Matter samples. + +Currently, only the :ref:`ot_cli_sample` sample is supported for Thread. +See the sample documentation for how to configure it. + +The Matter and Thread samples included in the limited customer sampling can work on the corresponding networks with standard devices of the same protocol. + +Programming Matter and Thread samples on the nRF54L15 PDK +========================================================= + +To program the compatible Matter or Thread samples on the nRF54L15 PDK, follow the :ref:`ug_nRF54l15_gs_sample` steps. +Read also programming guides prepared for specific Matter samples: + + * :ref:`Matter template sample ` + * :ref:`Matter light bulb sample ` + * :ref:`Matter light switch sample ` + * :ref:`Matter window covering sample ` + +Logging for Matter and Thread samples on the nRF54L15 PDK +========================================================= + +To read logs for Matter samples on the nRF54L15 PDK, complete the following steps: + +1. Connect to the nRF54L15 PDK using a USB cable. +#. Select the first available port to read the logs from. + +To read more about the logging see the :ref:`ug_nrf54l15_sample_reading_logs` section. + +.. _ug_nRF54l15_matter_thread_limitations: + +Limitations for Matter and Thread on the nRF54L15 PDK +***************************************************** + +Matter and Thread support has the following limitations on the nRF54L15 PDK: + +* Button 4 does not work on nRF54L15 PDK. + Bluetooth LE advertising for Matter commissioning starts automatically after the reboot. +* PWM driver module is not implemented and LED dimming does not work. + All PWM functions are replaced by constant LED states (:ref:`Matter window covering sample ` and :ref:`Matter light bulb sample `). +* Matter samples requires the nRF54L15 PDK to be at least revision ES3. + NRF54L15 PDK in revision ES2, which has been delivered within the v2.4.99-cs2 release, does not work with Matter samples. +* DFU over Bluetooth LE, Matter, or Serial Link is not yet implemented. +* The current implementation is not power-optimized. +* The PSA crypto API level 3 for storing security components is not yet implemented on the Secure Domain. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/constrained.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/constrained.rst index d36aaaa9cc8..ebe7d367505 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/constrained.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/constrained.rst @@ -1,7 +1,7 @@ .. _nRF70_nRF5340_constrained_host: -Operating with a resource constrained host -########################################## +Host device considerations +########################## .. contents:: :local: @@ -38,291 +38,3 @@ The nRF70 Series provides the following firmware patch optimizations to reduce t This patch variant is significantly smaller in size compared to the full-featured firmware patch variant that supports Wi-Fi :abbr:`STA (Station)` mode. * The nRF Wi-Fi driver offers support for either relocating or storing the patch in the external non-volatile memory if that is available. See :ref:`ug_nrf70_developing_fw_patch_ext_flash` for details. - -Zephyr OS factors -***************** -The following sections explain the factors that are applicable when using the Zephyr OS on the nRF5340 SoC. - -CPU frequency -============= - -The nRF5340 host has two operating frequencies, 64 MHz and 128 MHz, default frequency is 64 MHz. -For low power applications, it is recommended to use 64 MHz as the CPU frequency, but the Wi-Fi performance of the nRF70 Series device might be impacted. -For high performance applications, it is recommended to use 128 MHz as the CPU frequency. - -.. _constrained_host_networking_stack: - -Networking stack -================ - -The nRF70 Series driver uses the Zephyr networking stack for Wi-Fi protocol implementation. -You can configure the networking stack to use different networking buffers and queue depths. -The nRF70 Series driver can be configured to use different numbers of TX buffers and RX buffers based on the use case. -A separate configuration option is provided to configure the number of packets, and the number of buffers used by each packet can also be configured. - -The following table explains the configuration options: - -+------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+ -|Configuration Option | Values | Description | -+==========================================+=============================+==========================================================================================================================+ -|:kconfig:option:`CONFIG_NET_PKT_TX_COUNT` | ``1`` - Unlimited | Number of TX packets. This is the TX queue depth, higher depth saturates the Wi-Fi link but consumes more memory, | -| | (based on available memory) | lower depth reduces memory usage but does not saturate the Wi-Fi link leading to poor performance. | -+------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| :kconfig:option:`CONFIG_NET_PKT_RX_COUNT`| ``1`` - Unlimited | Number of RX packets. This is the RX queue depth, higher depth can keep up with the RX traffic but consumes more memory, | -| | (based on available memory) | lower depth reduces memory usage but does not keep up with the RX traffic leading to packet drops. | -+------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| :kconfig:option:`CONFIG_NET_BUF_TX_COUNT`| ``1`` - Unlimited | Number of TX buffers. Typically for Wi-Fi, each packet has two buffers, | -| | (based on available memory) | so this has to be twice the number of packets. | -+------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| :kconfig:option:`CONFIG_NET_BUF_RX_COUNT`| ``1`` - Unlimited | Number of RX buffers. Typically for Wi-Fi, each packet has one buffer, | -| | (based on available memory) | so this has to be equal to the number of packets. | -+------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+ - -.. _constrained_host_driver_memory_controls: - -nRF70 Series driver performance and memory fine-tuning controls -*************************************************************** - -The nRF70 Series driver provides the following software configurations to fine-tune memory and performance based on the use case: - -.. list-table:: - :header-rows: 1 - - * - Configuration Option - - Values - - Description - - Impact - - Purpose - * - :kconfig:option:`CONFIG_WPA_SUPP` - - ``y`` or ``n`` - - Enable or disable Wi-Fi Protected Access (WPA) supplicant - - Memory savings - - This specifies the inclusion of the WPA supplicant module. - Disabling this flag restricts the nRF70 Series driver's functionality to STA scan only. - * - :kconfig:option:`CONFIG_NRF700X_AP_MODE` - - ``y`` or ``n`` - - Enable or disable Access Point (AP) mode - - Memory savings - - This specifies the inclusion of the AP mode module. - Disabling this flag restricts the nRF70 Series driver's functionality to :term:`Station mode (STA)` only. - * - :kconfig:option:`CONFIG_NRF700X_P2P_MODE` - - ``y`` or ``n`` - - Enable or disable Wi-Fi direct mode - - Memory Savings - - This specifies the inclusion of the P2P mode module. - Disabling this flag restricts the nRF70 Series driver's functionality to STA or AP mode only. - * - :kconfig:option:`CONFIG_NRF700X_MAX_TX_TOKENS` - - ``5``, ``10``, ``11``, ``12`` - - Maximum number of TX tokens. - These are distributed across all WMM access categories (including a pool for all). - - Performance tuning and Memory savings - - This specifies the maximum number of TX tokens that can be used in the token bucket algorithm. - More tokens imply more concurrent transmit opportunities for RPU but can lead to poor aggregation performance - if the pipeline is not saturated. But to saturate the pipeline, a greater number of networking stack buffers, - or queue depth, is required. - * - :kconfig:option:`CONFIG_NRF700X_MAX_TX_AGGREGATION` - - ``1`` to ``Unlimited`` (based on available memory in nRF70 Series device) - - Maximum number of frames that are coalesced into a single Wi-Fi frame (e.g., MPDU's in an A-MPDU, or MSDU's in an A-MSDU). - The coalescing greatly improves the throughput for small frames or under high traffic load. - - Performance tuning and Memory savings - - This specifies the maximum number of frames that can be coalesced into a single Wi-Fi frame. - More frames imply more coalescing opportunities but can add latency to the TX path as we wait for more frames to arrive. - * - :kconfig:option:`CONFIG_NRF700X_RX_NUM_BUFS` - - ``1`` to ``Unlimited`` (based on available memory in nRF70 Series device) - - Number of RX buffers - - Memory savings - - This specifies the number of RX buffers that can be used by the nRF70 Series driver. - The number of buffers must be enough to keep up with the RX traffic, otherwise packets might be dropped. - * - :kconfig:option:`CONFIG_NRF700X_TX_MAX_DATA_SIZE` - - ``64`` to ``1600`` - - Maximum TX data size - - Memory savings - - This specifies the maximum size of Wi-Fi protocol frames that can be transmitted. - Large frame sizes imply more memory usage but can efficiently utilize the bandwidth. - If the application does not need to send large frames, then this can be reduced to save memory. - * - :kconfig:option:`CONFIG_NRF700X_RX_MAX_DATA_SIZE` - - ``64`` to ``1600`` - - Maximum RX data size - - Memory savings - - This controls the maximum size of the frames that can be received by the Wi-Fi protocol. - Large frame sizes imply more memory usage but can efficiently utilize the bandwidth. - If the application does not need to receive large frames, then this can be reduced to save memory. - -The configuration options must be used in conjunction with the Zephyr networking stack configuration options to achieve the desired performance and memory usage. -These options form a staged pipeline all the way to the nRF70 Series chip, any change in one stage of the pipeline will impact the performance and memory usage of the next stage. -For example, solving bottleneck in one stage of the pipeline might lead to a bottleneck in the next stage. - -.. _constrained_host_packet_memory: - -nRF70 Series packet memory -************************** -The nRF70 Series device chipset has a special memory called the packet memory to store the Wi-Fi protocol frames for both TX and RX. -The various configuration options that control the size of the packet memory are listed below: - -* :kconfig:option:`CONFIG_NRF700X_TX_MAX_DATA_SIZE` -* :kconfig:option:`CONFIG_NRF700X_RX_MAX_DATA_SIZE` -* :kconfig:option:`CONFIG_NRF700X_MAX_TX_TOKENS` -* :kconfig:option:`CONFIG_NRF700X_MAX_TX_AGGREGATION` -* :kconfig:option:`CONFIG_NRF700X_RX_NUM_BUFS` - -The packet memory is divided into two parts, one for TX and one for RX. The size of the TX packet memory is calculated as follows: - -.. code-block:: none - - (CONFIG_NRF700X_TX_MAX_DATA_SIZE + 52 ) * CONFIG_NRF700X_MAX_TX_TOKENS * CONFIG_NRF700X_MAX_TX_AGGREGATION - -The size of the RX packet memory is calculated as follows: - -.. code-block:: none - - CONFIG_NRF700X_RX_MAX_DATA_SIZE * CONFIG_NRF700X_RX_NUM_BUFS - -The total packet memory size is calculated as follows: - -.. code-block:: none - - (CONFIG_NRF700X_TX_MAX_DATA_SIZE + 52 ) * CONFIG_NRF700X_MAX_TX_TOKENS * CONFIG_NRF700X_MAX_TX_AGGREGATION + - CONFIG_NRF700X_RX_MAX_DATA_SIZE * CONFIG_NRF700X_RX_NUM_BUFS - -There is a build time check to ensure that the total packet memory size does not exceed the available packet memory size in the nRF70 Series chip. - -.. note:: - The ``52`` bytes in the above equations are the overhead bytes required by the nRF70 Series chip to store the headers and footers of the Wi-Fi protocol frames. - -.. _constrained_host_usage_profiles: - -Usage profiles -************** - -The nRF70 Series driver can be used in the following profiles (not an exhaustive list): - -.. list-table:: - :header-rows: 1 - - * - Features - - Profile - - Configuration Options - - Use cases - - Throughputs - * - STA scan only - - Scan only - - ``CONFIG_WPA_SUPP=n`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=1`` - ``CONFIG_NET_PKT_RX_COUNT=1`` - ``CONFIG_NET_BUF_TX_COUNT=1`` - ``CONFIG_NET_BUF_RX_COUNT=1`` - - Location services - - ``N/A`` - * - :abbr:`STA (Station)` mode - - IoT devices - - ``CONFIG_WPA_SUPP=y`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=6`` - ``CONFIG_NET_PKT_RX_COUNT=6`` - ``CONFIG_NET_BUF_TX_COUNT=12`` - ``CONFIG_NET_BUF_RX_COUNT=6`` - ``CONFIG_NRF700X_RX_NUM_BUFS=6`` - ``CONFIG_NET_BUF_DATA_SIZE=800`` - ``CONFIG_HEAP_MEM_POOL_SIZE=230000`` - ``CONFIG_SPEED_OPTIMIZATIONS=y`` - ``CONFIG_NRF700X_UTIL=n`` - ``CONFIG_NRF700X_MAX_TX_AGGREGATION=1`` - ``CONFIG_NRF700X_MAX_TX_TOKENS=5`` - - IoT devices - - ``TCP-TX: 5.2 Mbps`` - ``TCP-RX: 3.4 Mbps`` - ``UDP-TX: 5.5 Mbps`` - ``UDP-RX: 4.1 Mbps`` - * - :abbr:`STA (Station)` mode - - Memory optimized :abbr:`STA (Station)` mode - - ``CONFIG_WPA_SUPP=y`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=6`` - ``CONFIG_NET_PKT_RX_COUNT=6`` - ``CONFIG_NET_BUF_TX_COUNT=12`` - ``CONFIG_NET_BUF_RX_COUNT=6`` - ``CONFIG_NRF700X_RX_NUM_BUFS=6`` - ``CONFIG_NET_BUF_DATA_SIZE=500`` - ``CONFIG_HEAP_MEM_POOL_SIZE=230000`` - ``CONFIG_SPEED_OPTIMIZATIONS=y`` - ``CONFIG_NRF700X_UTIL=n`` - ``CONFIG_NRF700X_MAX_TX_AGGREGATION=1`` - ``CONFIG_NRF700X_MAX_TX_TOKENS=5`` - - Sensors with low data requirements - - ``TCP-TX: 0.3 Mbps`` - ``TCP-RX: 1.5 Mbps`` - ``UDP-TX: 5.1 Mbps`` - ``UDP-RX: 0.5 Mbps`` - * - :abbr:`STA (Station)` mode - - High performance :abbr:`STA (Station)` mode - - ``CONFIG_WPA_SUPP=y`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=30`` - ``CONFIG_NET_PKT_RX_COUNT=30`` - ``CONFIG_NET_BUF_TX_COUNT=60`` - ``CONFIG_NET_BUF_RX_COUNT=30`` - ``CONFIG_NET_BUF_DATA_SIZE=1100`` - ``CONFIG_HEAP_MEM_POOL_SIZE=230000`` - ``CONFIG_SPEED_OPTIMIZATIONS=y`` - ``CONFIG_NRF700X_UTIL=n`` - ``CONFIG_NRF700X_MAX_TX_AGGREGATION=9`` - ``CONFIG_NRF700X_MAX_TX_TOKENS=12`` - - High data rate IoT devices - - ``TCP-TX: 14.2 Mbps`` - ``TCP-RX: 7.4 Mbps`` - ``UDP-TX: 26.2 Mbps`` - ``UDP-RX: 12.4 Mbps`` - * - :abbr:`STA (Station)` mode - - TX prioritized :abbr:`STA (Station)` mode - - ``CONFIG_WPA_SUPP=y`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=32`` - ``CONFIG_NET_PKT_RX_COUNT=10`` - ``CONFIG_NET_BUF_TX_COUNT=64`` - ``CONFIG_NET_BUF_RX_COUNT=10`` - ``CONFIG_NRF700X_RX_NUM_BUFS=10`` - ``CONFIG_NET_BUF_DATA_SIZE=1100`` - ``CONFIG_HEAP_MEM_POOL_SIZE=230000`` - ``CONFIG_SPEED_OPTIMIZATIONS=y`` - ``CONFIG_NRF700X_UTIL=n`` - ``CONFIG_NRF700X_MAX_TX_AGGREGATION=9`` - ``CONFIG_NRF700X_MAX_TX_TOKENS=12`` - - Sensors with high data rate - - ``TCP-TX: 9.2 Mbps`` - ``TCP-RX: 3.6 Mbps`` - ``UDP-TX: 26.6 Mbps`` - ``UDP-RX: 12.8 Mbps`` - * - :abbr:`STA (Station)` mode - - RX prioritized :abbr:`STA (Station)` mode - - ``CONFIG_WPA_SUPP=y`` - ``CONFIG_NRF700X_AP_MODE=n`` - ``CONFIG_NRF700X_P2P_MODE=n`` - ``CONFIG_NET_PKT_TX_COUNT=5`` - ``CONFIG_NET_PKT_RX_COUNT=64`` - ``CONFIG_NET_BUF_TX_COUNT=10`` - ``CONFIG_NET_BUF_RX_COUNT=64`` - ``CONFIG_NRF700X_RX_NUM_BUFS=64`` - ``CONFIG_NET_BUF_DATA_SIZE=1100`` - ``CONFIG_HEAP_MEM_POOL_SIZE=230000`` - ``CONFIG_SPEED_OPTIMIZATIONS=y`` - ``CONFIG_NRF700X_UTIL=n`` - ``CONFIG_NRF700X_MAX_TX_AGGREGATION=2`` - ``CONFIG_NRF700X_MAX_TX_TOKENS=5`` - - Display devices streaming data - - ``TCP-TX: 5.3 Mbps`` - ``TCP-RX: 7.9 Mbps`` - ``UDP-TX: 8.6 Mbps`` - ``UDP-RX: 12.7 Mbps`` - -.. note:: - The measured throughputs, as shown in the table above, are based on tests conducted using the nRF7002 DK. - The results represent the best throughput, averaged over three iterations, and were obtained with a good RSSI signal in a clean environment. - - The above configuration values can be passed using standard ways such as CMake arguments to west build (`Zephyr One Time Arguments`_ or `Zephyr Permanent Arguments`_), or by adding them in an :file:`overlay` file and passing to west build as CMake argument ``EXTRA_CONF_FILE``. - See `Zephyr Application Configuration`_ for more details. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/debugging.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/debugging.rst deleted file mode 100644 index ca6ed6c7028..00000000000 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/debugging.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. _ug_nrf70_developing_debugging: - -Debugging -######### - -.. contents:: - :local: - :depth: 2 - -This guide describes how to debug applications that use the nRF70 Series companion chips. - -Software -******** - -The scope of this section is limited to the nRF70 driver, WPA supplicant and networking stack. - -Enable debug features -===================== - -The nRF70 driver, WPA supplicant, and networking stack have debug features that can be enabled to help debug issues. - -You can enable debug features by using Zephyr's configuration :ref:`snippets` feature. - -For example, to build the :ref:`wifi_shell_sample` sample for the nRF7002 DK with debugging enabled, run the following commands: - -With west ---------- - -.. code-block:: console - - west build -p -b nrf7002dk_nrf5340_cpuapp -S nrf70-debug samples/wifi/shell - -With CMake ----------- - -.. code-block:: console - - cmake -GNinja -Bbuild -DBOARD=nrf7002dk_nrf5340_cpuapp -DSNIPPET=nrf70-debug samples/wifi/shell - ninja -C build - -Statistics -========== - -The nRF70 driver, firmware, and networking stack have statistics feature that can be enabled to help debug issues. - -You can enable statistics by using the ``nrf70-debug`` snippet. -See `Enable debug features`_. - -.. list-table:: Statistics table - :header-rows: 1 - - * - Command - - Description - - Functional area - * - ``net stats`` - - Displays statistics for the networking stack, network interfaces, and network protocols. - - Data path debugging (Networking stack) - * - ``wifi statistics`` - - Displays frame statistics for the nRF70 driver. - - Data path debugging (Wi-Fi driver) - * - ``wifi_util tx_stats `` - - Displays transmit statistics for the nRF70 driver. - - Data path debugging (Wi-Fi driver TX) - * - ``wifi_util rpu_stats all`` [1]_ - - Displays statistics for the nRF70 firmware (all modules, support for specific modules is also available). - - nRF70 firmware debugging (Data and control path) -.. [1] This command only works when the nRF70 control plane is functional, as it uses the control plane to retrieve the statistics. - -.. note:: - All statistics, especially data path statistics, must be collected multiple times to see the incremental changes and understand the behavior. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/fw_patches_ext_flash.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/fw_patches_ext_flash.rst index c12f7dddf8a..44f5321f4e9 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/fw_patches_ext_flash.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/fw_patches_ext_flash.rst @@ -10,15 +10,15 @@ Firmware patches in the external memory This guide explains the available options for having the nRF70 Series firmware patches reside in the external memory. .. note:: - External memory refers to the memory that is outside the SoC, for example, an external flash memory chip, or external non-volatile memory (NVM) chip etc. + External memory refers to the memory that is outside the SoC, for example, an external flash memory chip, or external non-volatile memory (NVM) chip. Overview ******** -By default the nRF70 Series firmware patches are built as part of the nRF Wi-Fi host driver code, residing in on-chip memory. +By default, the nRF70 Series firmware patches are built as part of the nRF Wi-Fi driver code, residing in on-chip memory. The firmware patches include code that is executed on the nRF70 Series device. -The size of the firmware patches may be considerably large, which limits the amount of on-chip code memory available for the user application. -In order to increase the amount of on-chip memory available for user applications, the nRF70 Series Wi-Fi driver supports the option of using external memory, if that is available. +The size of the firmware patches might be considerably large, which limits the amount of on-chip code memory available for the user application. +In order to increase the amount of on-chip memory available for user applications, the nRF Wi-Fi driver supports the option of using external memory, if that is available. Prerequisites ============= @@ -30,7 +30,7 @@ Before using this feature, make sure that the following prerequisites are comple The maximum size of all the firmware patches combined is 128 KB. .. note:: - Currently, in Nordic Semiconductor SoCs, access to external memory and the Execute in Place (XIP) feature are available through the QSPI interface only. + Currently, in Nordic Semiconductor SoCs, access to external memory and the Execute in Place (XIP) feature are available through the QSPI interface only. Supported platforms =================== @@ -41,27 +41,27 @@ The following platforms are supported: * nRF52840 DK with nRF7002 EK as a shield .. note:: - Due to limitations mentioned above, the nRF7002 DK is not supported as it needs access to external memory through the SPI interface. + Due to limitations mentioned above, the nRF7002 DK is not supported as it needs access to external memory through the SPI interface. Available options ***************** There are two supported options for offloading the firmware patches in the external memory feature: -* using XIP access -* using QSPI transfers to RAM +* Using XIP access +* Using QSPI transfers to RAM -using XIP access +Using XIP access ================ If the application supports XIP from external memory, then the firmware patches can be loaded as part of the nRF Wi-Fi driver code (RODATA) and then relocated to the external memory. The nRF Wi-Fi driver accesses the firmware patches using XIP feature and downloads the firmware patches to the nRF70 device. -To enable this feature, set the :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_XIP` kconfig option to ``y``. +To enable this feature, set the :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_XIP` Kconfig option to ``y``. Once the build is complete, the feature can be verified by checking the memory regions summary in the build output. A new memory region called ``EXTFLASH`` is added to the memory regions summary, and the firmware patches are placed in this region. The size of the ``FLASH`` used is reduced by the size of the firmware patches. -A sample memory regions summary is shown below: +Following is a sample summary of the memory regions: .. code-block:: console @@ -71,29 +71,29 @@ A sample memory regions summary is shown below: RAM: 170636 B 448 KB 37.20% IDT_LIST: 0 GB 2 KB 0.00% -using QSPI transfers to RAM +Using QSPI transfers to RAM =========================== The nRF Wi-Fi driver supports the option for offloading the nRF70 firmware patch to external non-XIP memory. In this case the upload of the firmware patch from the external memory to the nRF70 device happens in two stages: -* first the firmware patch is loaded from the external memory onto internal RAM and -* then it is uploaded to the nRF70 device. +1. The firmware patch is loaded from the external memory onto internal RAM. +#. The firmware patch is uploaded to the nRF70 device. -This feature can be enabled using DTS or :ref::`snippets` feature or by using :ref::`partition_manager`. +This feature can be enabled using DTS or :ref:`snippets` feature or by using :ref:`partition_manager`. Configuration ------------- The following configuration options are available: -* :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE`: Enables the option to store the firmware patch in external non-XIP memory. -* :kconfig:option:`CONFIG_NRF_WIFI_FW_FLASH_CHUNK_SIZE`: Defines the size of the chunks used to read the firmware patches from the external non-XIP memory. +* :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE` - Enables the option to store the firmware patch in external non-XIP memory. +* :kconfig:option:`CONFIG_NRF_WIFI_FW_FLASH_CHUNK_SIZE` - Defines the size of the chunks used to read the firmware patches from the external non-XIP memory. The default value is 8192 bytes. The external memory partition name must be defined in the devicetree or in the partition manager configuration file. -* ``nrf70_fw_partition``: Defines the name of the external memory partition that stores the firmware patches. +* ``nrf70_fw_partition`` - Defines the name of the external memory partition that stores the firmware patches. This must be defined in the devicetree, for example: .. code-block:: dts @@ -110,7 +110,7 @@ The external memory partition name must be defined in the devicetree or in the p }; }; -* ``nrf70_wifi_fw`` : Defines the name of the external memory partition that stores the firmware patches. +* ``nrf70_wifi_fw`` - Defines the name of the external memory partition that stores the firmware patches. This must be defined in the partition manager configuration file, for example: .. code-block:: console @@ -126,9 +126,9 @@ Building See :ref:`nrf7002dk_nrf5340` for general instructions on building. -Additionally, you must enable either the `nrf70-fw-patch-ext-flash` snippet or the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` option. +Additionally, you must enable either the ``nrf70-fw-patch-ext-flash`` snippet or the :kconfig:option:`CONFIG_PARTITION_MANAGER_ENABLED` option. -For example, to build the :ref:`wifi_shell_sample` sample for the nRF5340 DK with the ``nrf70-fw-patch-ext-flash`` snippet enabled, run the following commands: +For example, to build the :ref:`wifi_shell_sample` sample for the nRF5340 DK with the ``nrf70-fw-patch-ext-flash`` snippet enabled, run the following commands. With west ^^^^^^^^^ @@ -165,7 +165,7 @@ With CMake Programming ----------- -To program the firmware image with the firmware patches stored in the external memory, use the following commands: +To program the firmware image with the firmware patches stored in the external memory, use the following commands. With west ^^^^^^^^^ @@ -185,4 +185,12 @@ For example, for nrfjprog: .. code-block:: console - nrfjprog -f nrf53 -s 0 --program build/zephyr/merged.hex ---sectorerase --qspisectorerase --verify --reset + nrfjprog -f nrf53 -s 0 --program build/zephyr/merged.hex ---sectorerase --qspisectorerase --verify --reset + +Updating firmware patches +========================= + +You can update the firmware patches using all available DFU alternatives described in the main :ref:`ug_fw_update` page. +To do it, you need to use MCUboot bootloader and create proper partitions to allow storing and replacing the firmware patches. + +To learn how to prepare your application and perform the firmware patch update, see the :ref:`ug_nrf70_fw_patch_update` page. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/images/nrf70_ug_overview.svg b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/images/nrf70_ug_overview.svg similarity index 100% rename from doc/nrf/device_guides/working_with_nrf/nrf70/images/nrf70_ug_overview.svg rename to doc/nrf/device_guides/working_with_nrf/nrf70/developing/images/nrf70_ug_overview.svg diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/index.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/index.rst index a3517167bec..b95344e6c47 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/index.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/index.rst @@ -3,16 +3,17 @@ Developing with nRF70 Series ############################ -The |NCS| provides support for development on the nRF70 Series, using the nRF7002 DK (PCA10143) that includes the Wi-Fi® companion IC. +The |NCS| provides support for developing networking applications with Wi-Fi® connectivity using the nRF70 Series companion IC devices. +Applications can be developed on the nRF7002 DK (PCA10143), which includes the nRF7002 companion IC, or on boards compatible with the nRF7002 EK (PCA63556) or the nRF7002 EB (PCA63561). + +The following subpages cover topics related to developing applications with the nRF70 Series ICs using the respective development and evaluation boards. .. toctree:: :maxdepth: 2 :caption: Subpages: - powersave + stack_partitioning constrained - regulatory_support - scan_operation - debugging fw_patches_ext_flash - raw_tx_operation + nrf70_fw_patch_update + power_profiling diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/nrf70_fw_patch_update.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/nrf70_fw_patch_update.rst new file mode 100644 index 00000000000..67d417b9a5c --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/nrf70_fw_patch_update.rst @@ -0,0 +1,211 @@ +.. _ug_nrf70_fw_patch_update: + +Firmware patch update +##################### + +.. contents:: + :local: + :depth: 2 + +This guide explains the available option for updating the nRF70 Series firmware patches that reside in the external memory using the Device Firmware Updates (DFU) procedure. + +.. note:: + External memory refers to the memory that is outside the System-on-Chip (SoC), for example, an external flash memory chip, or an external nonvolatile memory (NVM) chip. + +.. note:: + Currently, you cannot build an example with the both :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE` and :kconfig:option:`CONFIG_XIP_SPLIT_IMAGE` Kconfig options enabled. + To enable XIP support use the :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_XIP` Kconfig option instead of the :kconfig:option:`CONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE` Kconfig option. + +Overview +======== + +By default, the patch is located in the on-chip memory as part of the nRF Wi-Fi driver code. +However, you have the option to store it in external memory, which frees up space in the on-chip memory. +If the patch is situated outside the SoC memory space, it will not be updated automatically during a regular firmware update of the application core. +In such cases, you must enable the DFU procedure specifically for the nRF70 Series firmware patch on your device. + +To learn more about the firmware patch located in the external memory, see the :ref:`ug_nrf70_developing_fw_patch_ext_flash` guide. + +Prerequisites +============= + +To use this feature, ensure that the following prerequisites are met: + +* The external memory is available and properly configured in the device tree. +* The external memory has sufficient capacity to accommodate the firmware patches. + This includes additional space for potential patch upgrades, such as those required for DFU. + The combined size of all firmware patches should not exceed 128 kB. +* MCUboot is enabled, and the :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` Kconfig option is set to ``y``. + +Supported platforms +=================== + +The following platforms are supported: + +* nRF5340 DK with nRF7002 EK as a shield + +Preparing the application +========================= + +The DFU procedure for the nRF70 Series firmware patch, when located in external memory, requires the creation of additional MCUboot partitions. +This can be accomplished using the Partition Manager by defining the necessary partition layout in the Partition Manager configuration file specific to your application. +For instructions on configuring basic partitions with the Partition Manager, refer to the :ref:`partition_manager` documentation. + +The instructions in this guide assume you are using the Partition Manager and its associated configuration files. + +.. _nrf70_fw_patch_update_mcuboot_partitions: + +Defining nRF70 Series MCUboot partitions +---------------------------------------- + +The number of MCUboot partitions required depends on the platform being used and its memory layout. +In addition to a partition dedicated to the nRF70 Series firmware patch, you will need to create specific partitions based on the platform: + +* For applications that are based on a single image, define a new partition with the number ``1``. +* For multi-image builds, define the subsequent partition to follow the last existing one. + +Below are examples of MCUboot partition names for updating the nRF70 Series firmware patch, which vary depending on the platform and the number of cores used: + +* For the nRF5340 DK in a single-core variant (without the network core): ``mcuboot_primary_1`` and ``mcuboot_secondary_1``. +* For the nRF5340 DK in a multi-core variant (with the network core): ``mcuboot_primary_2`` and ``mcuboot_secondary_2``. + +.. _nrf70_fw_patch_update_adding_partitions: + +Adding nRF70 Series firmware patch partitions +--------------------------------------------- + +The examples below assume that there are two existing MCUboot partitions (for the application and network cores) and that the starting address of the free external memory space is ``0x12f000``. + +To add the required partitions for the nRF70 Series firmware patch update, complete the following steps: + +1. Create the ``nrf70_wifi_fw_mcuboot_pad`` partition for the MCUboot header. + + This partition should start from the first available address in the external memory space and have a size equal to the MCUboot image header length. + + For example: + + .. code-block:: console + + nrf70_wifi_fw_mcuboot_pad: + address: 0x12f000 + size: 0x200 + device: MX25R64 + region: external_flash + +#. Create the ``nrf70_wifi_fw`` partition for the firmware patch. + + This partition should start from the end address of the previously created MCUboot header partition and have a size of 128 kB (``0x20000``). + + For example: + + .. code-block:: console + + nrf70_wifi_fw: + address: 0x12f200 + size: 0x20000 + device: MX25R64 + region: external_flash + +#. Create the ``mcuboot_primary_X`` partition for MCUboot where ``X`` represents the appropriate partition number as described previously. + + This partition should have the same starting address as the ``nrf70_wifi_fw_mcuboot_pad`` partition, and a size of 132 kB + 200 B aligned to the device's sector size. + It includes both the MCUboot header and the nRF70 Series firmware patch. + + For example, the MX25R64 device has a sector size of 4 kB, so the following configuration can be used: + + .. code-block:: console + + mcuboot_primary_2: + orig_span: &id003 + - nrf70_wifi_fw_mcuboot_pad + - nrf70_wifi_fw + span: *id003 + address: 0x12F000 + size: 0x21000 + device: MX25R64 + region: external_flash + +#. Create the ``mcuboot_secondary_X`` partition for MCUboot, where ``X`` represents the appropriate partition number as described in the :ref:`nrf70_fw_patch_update_mcuboot_partitions` section. + + This partition should start at the address immediately following the end of the ``mcuboot_primary_X`` partition and have the same size as the primary partition. + This partition will be used to store the new nRF70 Series firmware patch during the DFU procedure. + + For example: + + .. code-block:: console + + mcuboot_secondary_2: + address: 0x150000 + size: 0x21000 + device: MX25R64 + region: external_flash + +#. Update the ``external_flash`` partition to allocate all available memory space to it. + + For example: + + .. code-block:: console + + external_flash: + address: 0x171000 + size: 0x68F000 + device: MX25R64 + region: external_flash + +.. note:: + The actual configuration syntax for the Partition Manager will depend on the specific system and tools being used. + The example provided is for illustrative purposes and may need to be adjusted to fit the actual configuration file format and syntax required by the Partition Manager in use. + +Configuring build system +------------------------ + +To enable the DFU procedure for the nRF70 Series firmware patch, complete the following steps depending on the platform: + +* For the nRF5340 DK without the network core: + + 1. Set the :kconfig:option:`CONFIG_NRF_WIFI_FW_PATCH_DFU`` Kconfig option to ``y``. + #. Set the :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER`` Kconfig option to ``2``. + #. For the MCUBoot child image, set the :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER`` Kconfig option to ``2``. + +* For the nRF5340 DK with the network core: + + 1. Set the :kconfig:option:`CONFIG_NRF_WIFI_FW_PATCH_DFU`` Kconfig option to ``y``. + #. Set the :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER`` Kconfig option to ``3``. + #. For the MCUBoot child image, set the :kconfig:option:`CONFIG_UPDATEABLE_IMAGE_NUMBER`` Kconfig option to ``3``. + +For example, to build the sample with the DFU procedure for the nRF70 Series firmware patch on the nRF5340 DK platform, which includes the network core image, run the following commands: + +.. tabs:: + + .. group-tab:: West + + .. code-block:: console + + west build -d nrf5340dk_nrf5340_cpuapp -d -- -DSHIELD=nrf7002ek -DCONFIG_PARTITION_MANAGER_ENABLED=y -DCONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE=y -DCONFIG_NRF_WIFI_FW_PATCH_DFU=y -DCONFIG_UPDATEABLE_IMAGE_NUMBER=3 -Dmcuboot_CONFIG_UPDATEABLE_IMAGE_NUMBER=3 + + .. group-tab:: CMake + + .. code-block:: console + + cmake -GNinja -Bbuild -DBOARD=nrf5340dk_nrf5340_cpuapp -DSHIELD=nrf7002ek -DCONFIG_PARTITION_MANAGER_ENABLED=y -DCONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE=y -DCONFIG_NRF_WIFI_FW_PATCH_DFU=y -DCONFIG_UPDATEABLE_IMAGE_NUMBER=3 -Dmcuboot_CONFIG_UPDATEABLE_IMAGE_NUMBER=3 sample + ninja -C build + + .. group-tab:: nRF Connect for VS Code + + 1. When `building an application `_ as described in the |nRFVSC| documentation, follow the steps for setting up the build configuration. + #. In the Add Build Configuration screen, click the Add argument button under the Extra CMake argument section. + #. Add the following Kconfig options: + + .. code-block:: console + + -- -DSHIELD=nrf7002ek -DCONFIG_PARTITION_MANAGER_ENABLED=y -DCONFIG_NRF_WIFI_PATCHES_EXT_FLASH_STORE=y -DCONFIG_NRF_WIFI_FW_PATCH_DFU=y -DCONFIG_UPDATEABLE_IMAGE_NUMBER=3 -Dmcuboot_CONFIG_UPDATEABLE_IMAGE_NUMBER=3 + +If you want to use the :ref:`ug_multi_image` feature, you need to set the :kconfig:option:`CONFIG_DFU_MULTI_IMAGE_MAX_IMAGE_COUNT` Kconfig option to one of the following values: + +* For the nRF5340 DK without the network core: ``2`` +* For the nRF5340 DK with the network core: ``3`` + +Performing the update of the nRF70 Series firmware patch +======================================================== + +To perform the update of the nRF70 Series firmware patch, you can use all available DFU alternatives described in the :ref:`ug_fw_update` page. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/power_profiling.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/power_profiling.rst new file mode 100644 index 00000000000..67fd0f5a04e --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/power_profiling.rst @@ -0,0 +1,81 @@ +.. _ug_nrf70_developing_power_profiling: + +Power profiling of nRF7002 DK +############################# + +.. contents:: + :local: + :depth: 2 + +The Power Profiler Kit II (PPK2) of Nordic Semiconductor can be used in conjunction with the nRF7002 DK to evaluate the power consumption of nRF70 Series devices in Low-power mode. +To measure the power consumption of the nRF7002 DK, complete the following steps: + +1. Remove the jumper on **P23** (VBAT jumper). +#. Connect **GND** on the PPK2 kit to any **GND** on the nRF7002 DK. + You can use the **P21** pin **1** labeled as **GND** (-). +#. Connect the **Vout** on the PPK2 kit to the **P23** pin **1** on the nRF7002 DK. + + .. figure:: images/power_profiler2_pc_nrf7002_dk.png + :alt: Typical configuration for measuring power on the nRF7002 DK + + Typical configuration for measuring power on the nRF7002 DK + +#. Configure PPK2 as a source meter with 3.6 volts. + + The following image shows the Power Profiler Kit II example output for DTIM wakeup: + + .. figure:: images/power_profiler_dtim_wakeup.png + :alt: PPK2 output for DTIM wakeup + + PPK2 output for DTIM wakeup + + To reproduce the plots for DTIM period of 3, complete the following steps using the :ref:`wifi_shell_sample` sample: + + 1. Configure an AP with DTIM value of 3. + #. Connect to the AP using the following Wi-Fi shell commands: + + .. code-block:: console + + wifi scan + wifi connect + + #. Check the connection status using the following Wi-Fi shell command: + + .. code-block:: console + + wifi status + + The following image shows the PPK2 output for DTIM period of 3: + + .. figure:: images/power_profiler_dtim_output.png + :alt: PPK2 output for DTIM period of 3 + + PPK2 output for DTIM period of 3 + + To reproduce the plots for TWT interval of one minute, complete the following steps using the :ref:`wifi_shell_sample` sample: + + 1. Connect to a TWT supported Wi-Fi 6 AP using the following Wi-Fi shell commands: + + .. code-block:: console + + wifi scan + wifi connect + + #. Check the connection status using the following Wi-Fi shell command: + + .. code-block:: console + + wifi status + + #. Start a TWT session using the following Wi-Fi shell command: + + .. code-block:: console + + wifi twt setup 0 0 1 1 0 1 1 1 8 60000 + + The following image shows the PPK2 output for TWT interval of one minute: + + .. figure:: images/power_profiler_twt.png + :alt: PPK2 output for TWT + + PPK2 output for TWT diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/raw_tx_operation.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/raw_tx_operation.rst deleted file mode 100644 index d02ab9ef078..00000000000 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/raw_tx_operation.rst +++ /dev/null @@ -1,140 +0,0 @@ -.. _ug_nrf70_developing_raw_ieee_80211_packet_transmission: - -Raw IEEE 802.11 packet transmission -################################### - -.. contents:: - :local: - :depth: 2 - -The nRF70 Series device supports the transmission of raw IEEE 802.11 packets. -Raw IEEE 802.11 packets are packets that are not modified by the 802.11 Medium Access Control (MAC) layer during transmission by the nRF70 Series device. - -It is the responsibility of the application that intends to send the raw 802.11 packet to construct and provide a fully-conformant 802.11 packet along with the required set of packet TX and PHY parameters. -The MAC layer on the nRF70 Series device will transmit the raw 802.11 packets over-the-air using the provided packet data, TX, and PHY parameters. - -.. _ug_nrf70_developing_enabling_raw_packet_transmit_feature: - -Enabling raw packet transmit feature -************************************ - -To use the raw packet transmit feature in your applications, you must enable the :kconfig:option:`CONFIG_NRF700X_RAW_DATA_TX` Kconfig option in the project configuration. - -.. _ug_nrf70_developing_tx_injection_mode: - -TX injection mode -***************** - -The nRF70 Series device supports raw 802.11 packet transmission when TX injection mode is enabled in the nRF Wi-Fi driver. -To enable the TX injection mode of operation, you can use the ``NET_REQUEST_WIFI_MODE`` network management runtime API. -This API can be used to disable TX injection mode in the driver when raw 802.11 packet transmission is not required by the application. - -TX injection mode can be enabled when the nRF70 Series device operates in Station mode, both when it is operating in a connected Station mode or in a non-connected Station mode (not connected to an Access Point (AP)). - -When TX injection mode is enabled, you need to configure the operating channel. -This channel will be used as the default transmit channel when the nRF70 device operates in a non-connected Station mode. -When the device operates in Station mode connected to an AP on a given channel, the same channel will be used for raw 802.11 packet transmission. - -To set the desired channel for raw 802.11 packet transmission, you can use the ``NET_REQUEST_WIFI_CHANNEL`` network management API. - -See the :ref:`wifi_shell_sample` sample for more information on configuring mode and channel settings for raw packet transmission through shell commands. - -The following table lists the shell commands and network management APIs used to switch between operational modes and set channels: - -.. list-table:: Wi-Fi raw packet transmission network management APIs - :header-rows: 1 - - * - Network management APIs - - Wi-Fi shell command - - Example usage - - Description - * - net_mgmt(NET_REQUEST_WIFI_MODE) - - ``wifi mode -i `` - - ``wifi mode -i1 -st`` - - Configure interface instance 1 to Station with TX injection mode - * - net_mgmt(NET_REQUEST_WIFI_MODE) - - ``wifi mode -i `` - - ``wifi mode -i1 -s`` - - Configure interface instance 1 to Station mode - * - net_mgmt(NET_REQUEST_WIFI_CHANNEL) - - ``wifi channel -i `` - - ``wifi channel -i1 -c6`` - - Set the raw transmission channel to ``6`` for interface 1 to be used in non-connected Station mode - -.. _ug_nrf70_developing_tx_injection_mode_usage_requirements: - -TX injection mode usage requirements -************************************ - -The raw packet to be transmitted by an application must be a fully conformant IEEE 802.11 packet and must ensure that: - -* The packet has a valid 802.11 MAC header. -* The Frame Check Sequence (FCS) is not added to the packet by the application and is concatenated by the nRF70 Series device. - -.. note:: - If the packet is not a properly framed 802.11 packet, it will be dropped by the nRF70 Series device and will not be transmitted over-the-air. - -Additionally, the raw packet must provide transmit parameters that inform the nRF70 Series Wi-Fi device driver on how the packet must be transmitted. -It must also provide a packet marker identifying itself as a special packet, which must be handled differently by the nRF70 series Wi-Fi driver. -The transmit parameters and the packet marker together form the raw packet transmit header. -The raw packet transmit header is prepended to the 802.11 conformant raw packet before the packet is passed to the nRF Wi-Fi driver by the application. - -The following table lists the raw packet transmit header elements: - -.. list-table:: Wi-Fi raw packet transmission header elements - :header-rows: 1 - - * - Transmit and PHY parameters - - Description - * - magic_num - - Magic number to identify a raw packet. It is set to ``0x12345678``. - * - data_rate - - Data rate at which a packet is to be transmitted. It depends on the ``tx_mode`` parameter. If ``tx_mode`` is set to legacy mode, the data rate is the number provided. If ``tx_mode`` is set to HT, VHT, or HE mode, the data rate is the MCS rate. - * - packet_length - - Packet length of the 802.11 raw packet, excluding the raw transmit packet header length. - * - tx_mode - - Mode describing if the packet is VHT, HT, HE, or Legacy. - * - queue - - Wi-Fi access category mapping for packet. - * - raw_tx_flag - - Flag indicating raw packet transmission. This is reserved for driver use. - -You can refer to the relevant structures at: - -:file:`nrfxlib/nrf_wifi/fw_if/umac_if/inc/default/fmac_structs.h/raw_tx_pkt_header` - for the raw packet header. - -:file:`nrfxlib/nrf_wifi/fw_if/umac_if/inc/default/fmac_structs.h/nrf_wifi_fmac_ac` - for setting the ``queue`` parameter in the raw packet transmit header. - -:file:`nrfxlib/nrf_wifi/fw_if/umac_if/inc/default/fmac_structs.h/nrf_wifi_fmac_rawtx_mode` - for setting the ``tx_mode`` parameter in the raw packet transmit header. - -.. _ug_nrf70_developing_raw_packet_transmit_operation: - -Raw 802.11 packet transmit operation -************************************ - -The raw packet data has to be encompassed in an 802.11 packet and prepended with the raw transmit header before it is transmitted through raw socket to the nRF70 Wi-Fi device driver for transmission. -The packet is forwarded to the nRF70 Series device, which transmits the packet over-the-air. -All 802.11 MAC layer rules for the 802.11 packet (such as, link-layer acknowledgements, retransmissions) are handled by the nRF70 Series device. - -The following figure illustrates the packet structure and raw packet operation flow: - -.. figure:: images/nrf7000_packet_injection_tx_flow.png - :alt: Raw packet transmit packet structure and raw packet operation flow - - Raw packet transmit packet structure and raw packet operation flow - -.. _ug_nrf70_developing_operating_channel_for_raw_packet_transmission: - -Operating channel for raw packet transmission -********************************************* - -The channel configuration for raw packet transmission will be applied as follows: - -* Non-connected Station with TX injection mode configured and channel not set: The raw packet is transmitted on channel 1. -* Non-connected Station with TX injection mode configured and channel set by the user: The raw packet is transmitted on configured channel. -* Connected Station with TX injection mode configured: The raw packet is transmitted on the channel on which the device is connected to the AP. -* Station disconnected from the AP and TX injection mode configured (channel configured before connection to the AP): The raw packet is transmitted on the configured channel -* Station disconnected from the AP and TX injection mode configured (channel not configured before connection to the AP): The raw packet is transmitted on channel 1 (fallback channel). - -.. note:: - You must explicitly configure the channel for raw packet transmission when the device operates in non-connected Station mode. The device will use a fallback channel for raw packet transmission if one is not configured. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/developing/stack_partitioning.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/stack_partitioning.rst new file mode 100644 index 00000000000..412f2630ea2 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/developing/stack_partitioning.rst @@ -0,0 +1,19 @@ +.. _ug_nrf70_stack partitioning: + +Networking stack partitioning +############################# + +.. contents:: + :local: + :depth: 2 + +The nRF70 Series of wireless companion ICs implement the Physical (PHY) and Medium Access Control (MAC) layers of the IEEE 802.11 protocol stack. +The higher layers of the networking stack, namely, the nRF Wi-Fi driver and supplicant, the TCP/IP stack, and the networking application layers, run on the host device. +Data transfer between the host and the nRF70 companion device can occur through either SPI or QSPI interfaces. + +The following figure illustrates the partitioning of the Wi-Fi stack between the nRF70 Series device and the host device: + +.. figure:: images/nrf70_ug_overview.svg + :alt: Overview of nRF70 application architecture + + Overview of nRF70 application architecture diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/features.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/features.rst index 2d3a5bbc1c9..7a3083818b0 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/features.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/features.rst @@ -9,79 +9,47 @@ Features of nRF70 Series The nRF70 Series of wireless companion ICs add Wi-Fi® capabilities to another System-on-Chip (SoC), Microprocessor Unit (MPU), or Microcontroller (MCU) host device. It implements the Physical (PHY) and Medium Access Control (MAC) layers of the IEEE 802.11 protocol stack, while the higher layers of the networking stack run on the host device. -The nRF70 series wireless companion IC includes the RF front end and power management function. +The nRF70 Series wireless companion IC includes the RF front end and power management function. -The nRF70 series devices are designed for Internet of Things (IoT) applications and are ideal for adding modern Wi-Fi 6 capabilities to existing Bluetooth® Low Energy, Thread, or Zigbee systems, as well as adding Wi-Fi Access Point scanning capabilities to LTE/GPS systems. +The nRF70 Series devices are designed for Internet of Things (IoT) applications and are ideal for adding modern Wi-Fi 6 capabilities to existing Bluetooth® Low Energy, Thread, or Zigbee systems, as well as adding Wi-Fi Access Point scanning capabilities to LTE/GPS systems. For additional information, see the following documentation: +* `nRF70 Series`_ for the technical documentation on the nRF70 Series devices. +* :ref:`nrf7002dk_nrf5340`. +* :ref:`ug_nrf70_developing` documentation for topics related to developing Wi-Fi applications on nRF52, nRF53, and nRF91 Series, using the nRF70 companion IC devices. * :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. -* :ref:`nrf7002dk_nrf5340` - -The following figure illustrates the partitioning of the Wi-Fi stack between the nRF70 series device and the host device: - -.. figure:: images/nrf70_ug_overview.svg - :alt: Overview of nRF70 application architecture - - Overview of nRF70 application architecture - -Supported boards -**************** - -Devices in the nRF70 Series are supported by the following boards in the `Zephyr`_ open source project and in |NCS|. - -.. list-table:: - :header-rows: 1 - - * - DK or Prototype platform - - Companion module - - PCA number - - Build target - - Documentation - * - nRF7002 DK - - Not applicable - - PCA10143 - - ``nrf7002dk_nrf5340_cpuapp`` - - | `Product Specification `_ - | `User Guide `_ - * - nRF7001 emulation on nRF7002 DK - - Not applicable - - PCA10143 - - ``nrf7002dk_nrf7001_nrf5340_cpuapp`` - - | `nRF70 Series Specification `_ - * - nRF5340 DK - - nRF7002 EK - - PCA10095 - - ``nrf5340dk_nrf5340_cpuapp`` - - | `Product Specification `_ - | :ref:`Getting started ` - | `User Guide `_ - * - nRF52840 DK - - nRF7002 EK - - PCA10056 - - ``nrf52840dk_nrf52840`` - - | `Product Specification `_ - | :ref:`Getting started ` - | `User Guide `_ - * - nRF9160 DK - - nRF7002 EK - - PCA10090 - - ``nrf9160dk_nrf9160_ns`` - - | `Product Specification `_ - | :ref:`Getting started ` - | `User Guide `_ - * - Thingy:53 - - nRF7002 EB - - PCA20053 - - ``thingy53_nrf5340_cpuapp`` - - | :ref:`Getting started ` - | `User Guide `_ + +The nRF70 Series devices are Wi-Fi companion ICs and do not serve as standalone platforms for developing applications. +Wi-Fi applications may be developed on nRF52, nRF53, and nRF91 Series SoCs that support the nRF70 Series companion ICs. + +Supported protocols +******************* + +The nRF70 Series devices support the Wi-Fi protocol. +Wi-Fi is a half-duplex packet-based protocol operating on a fixed channel, using CSMA/CA for channel access. + +See the :ref:`ug_wifi` documentation for information related to the Wi-Fi protocol. Supported Wi-Fi standards and modes -*********************************** +=================================== -The nRF70 series wireless companion ICs add Wi-Fi 6 support to a host device that includes IP-based networking support. +The nRF70 Series wireless companion ICs add Wi-Fi 6 support to a host device that includes IP-based networking support. Wi-Fi 6 aligns with IEEE 802.11ax and all earlier versions of the IEEE 802.11 suite of wireless LAN standards. -Currently only Station (STA) support is included. -Access Point (AP) and peer-to-peer support in the form of Wi-Fi Direct will be available in the future. +Currently, the nRF70 Series devices support the following modes: + +* :ref:`Station (STA) `: Operates as a wireless client device. +* :ref:`Software-enabled Access Point (SoftAP or SAP) `: Operates as a virtual access point device. +* :ref:`Scan `: Operates as a scan-only device. +* :ref:`Radio test `: For PHY (Baseband and Radio) characterizations and calibrations. +* :ref:`Monitor `: Operates as an IEEE 802.11 wireless packet sniffer. + +The nRF70 Series devices also support the following functionalities: + +* :ref:`ug_nrf70_developing_raw_ieee_80211_packet_transmission`: Allows the injection of raw IEEE 802.11 frames in Station and Monitor modes. +* :ref:`Promiscuous reception `: Allows the reception of IEEE 802.11 packets from a connected BSSID when operating in Station mode. + +Peer-to-peer support in the form of Wi-Fi Direct® will be available in the future. + +See the :ref:`ug_wifi` documentation for more information related to Wi-Fi modes of operation. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/gs.rst index 534bd611254..b9e0e6caff3 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf70/gs.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/gs.rst @@ -1,35 +1,39 @@ .. _nrf7002dk_nrf5340: +.. _ug_nrf7002_gs: -Getting started with nRF70 Series -################################# +Getting started with nRF7002 DK +############################### .. contents:: :local: :depth: 4 -This page gets you started with your nRF70 Series devices using the |NCS|. +This page gets you started with your nRF7002 :term:`Development Kit (DK)` using the |NCS|. +It tells you how to install the :ref:`wifi_scan_sample` sample and perform a quick test of your DK. -If you want to go through an online training course to familiarize yourself with Wi-Fi® and the development of Wi-Fi applications, enroll in the `Wi-Fi Fundamentals course`_ in the `Nordic Developer Academy`_. - -Supported development boards -**************************** +If you have already set up your nRF7002 DK and want to learn more, see the following documentation: -nRF7002 DK -========== +* :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. +* :ref:`ug_nrf70_developing` documentation for more advanced topics related to the nRF70 Series. +* :ref:`ug_wifi` documentation for information related to Wi-Fi protocol and Wi-Fi modes of operation. -The nRF7002 DK (PCA10143) is a single-board development kit for evaluation and development on the nRF7002, a Wi-Fi companion :term:`Integrated Circuit (IC)` to Nordic Semiconductor's nRF5340 System-on-Chip (SoC) host processor. +If you want to go through an online training course to familiarize yourself with Wi-Fi® and the development of Wi-Fi applications, enroll in the `Wi-Fi Fundamentals course`_ in the `Nordic Developer Academy`_. Overview --------- +******** + +The nRF7002 DK (PCA10143) is a single-board development kit for evaluation and development on the nRF7002, a Wi-Fi companion :term:`Integrated Circuit (IC)` to Nordic Semiconductor's nRF5340 System-on-Chip (SoC) host processor. +It is certified for the Wi-Fi Alliance® `certification program `_ in the Connectivity, Security, and Optimization categories. +See :ref:`ug_wifi_certification` for detailed information. The nRF7002 is an IEEE 802.11ax (Wi-Fi 6) compliant solution that implements the Wi-Fi physical layer and Medium Access Control (MAC) layer protocols. -It implements the Wi-Fi driver software on the nRF5340 host processor communicating over the QSPI bus. +It implements the nRF Wi-Fi driver software on the nRF5340 host processor communicating over the QSPI bus. The nRF5340 host is a dual-core SoC based on the Arm® Cortex®-M33 architecture. It has the following features: -* 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*. +* 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 ``nrf7002dk_nrf5340_cpuapp`` build target provides support for the application core on the nRF5340 SoC. The ``nrf7002dk_nrf5340_cpunet`` build target provides support for the network core on the nRF5340 SoC. @@ -39,17 +43,24 @@ The ``nrf7002dk_nrf5340_cpunet`` build target provides support for the network c nRF7002 DK +Minimum requirements +******************** + +Make sure you have all the required hardware and that your computer and mobile device both have one of the supported operating systems. Hardware --------- +======== -The nRF7002 DK has two external oscillators: +* nRF7002 DK: + The nRF7002 DK has two external oscillators. - * The frequency of the slow clock is 32.768 kHz. - * The frequency of the main clock is 32 MHz. + * The frequency of the slow clock is 32.768 kHz. + * The frequency of the main clock is 32 MHz. + +* Micro-USB 2.0 cable Supported features -^^^^^^^^^^^^^^^^^^ +------------------ The ``nrf7002dk_nrf5340_cpuapp`` board configuration supports the following hardware features: @@ -127,36 +138,36 @@ The ``nrf7002dk_nrf5340_cpunet`` board configuration supports the following hard Other hardware features are not supported by the |NCS| kernel. Connections and IOs -^^^^^^^^^^^^^^^^^^^ +------------------- The connections and IOs supported by the development kit are listed in this section. LED -""" +^^^ -* LED1 (green) = P1.06 -* LED2 (green) = P1.07 +* **LED 1** (green) = **P1.06** +* **LED 2** (green) = **P1.07** Push buttons -"""""""""""" +^^^^^^^^^^^^ -* BUTTON1 = SW1 = P1.08 -* BUTTON2 = SW2 = P1.09 -* BOOT = SW5 = boot/reset +* **Button 1** = **SW1** = **P1.08** +* **Button 2** = **SW2** = **P1.09** +* **BOOT** = **SW5** = boot/reset Wi-Fi control -""""""""""""" +^^^^^^^^^^^^^ -* BUCKEN = P0.12 -* IOVDD CONTROL = P0.31 -* HOST IRQ = P0.23 -* COEX_REQ = P0.28 -* COEX_STATUS0 = P0.30 -* COEX_STATUS1 = P0.29 -* COEX_GRANT = P0.24 +* BUCKEN = **P0.12** +* IOVDD CONTROL = **P0.31** +* HOST IRQ = **P0.23** +* COEX_REQ = **P0.28** +* COEX_STATUS0 = **P0.30** +* COEX_STATUS1 = **P0.29** +* COEX_GRANT = **P0.24** Security components -^^^^^^^^^^^^^^^^^^^ +------------------- The following security components are available: @@ -167,350 +178,173 @@ The following security components are available: * Secure boot. -Programming and debugging -------------------------- - -The nRF5340 application core supports the Armv8-M Security Extension. -Applications built for the ``nrf7002dk_nrf5340_cpuapp`` board boot by default in the secure state. +Software +======== -The nRF5340 network core does not support the Armv8-M Security Extension. -nRF5340 IDAU can configure bus accesses by the nRF5340 network core to have the secure attribute set. -This allows to build and run secure-only applications on the nRF5340 SoC. +On your computer, one of the following operating systems: -Building |NCS| applications with Arm TrustZone -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Microsoft Windows +* macOS +* Ubuntu Linux -Applications on nRF5340 can use Cortex-M Security Extensions (CMSE) and separate firmware for the application core between Secure Processing Environment (SPE) and Non-Secure Processing Environment (NSPE). -You can build SPE using either |NCS| or `Trusted Firmware M`_ (TF-M). -You must always build NSPE using |NCS|. +|Supported OS| -For information about Cortex-M Security Extensions (CMSE) and the difference between the two environments, see :ref:`app_boards_spe_nspe`. +On your mobile device, one of the following operating systems: -.. note:: - By default, SPE for the nRF5340 application core is built using TF-M. +* Android +* iOS -Building the firmware with TF-M -""""""""""""""""""""""""""""""" +Installing the required software +******************************** -If you want to use |NCS| to build the firmware image separated in SPE with TF-M and NSPE, complete the following steps: +On your computer, install `nRF Connect for Desktop`_. +After installing and starting the application, install the Programmer app. -1. Build the |NCS| application for the application core using the ``nrf7002dk_nrf5340_cpuapp_ns`` build target. +You must also install a terminal emulator, such as `nRF Connect Serial Terminal`_, the nRF Terminal (part of the `nRF Connect for Visual Studio Code`_ extension), or PuTTY. +nRF Connect Serial Terminal is the recommended method for :ref:`nrf70_gs_connecting`. - To invoke the building of TF-M, the |NCS| build system requires the Kconfig option :kconfig:option:`CONFIG_BUILD_WITH_TFM` to be enabled, which is set by default when building |NCS| as an application that supports both NSPE and SPE. +On your mobile device, install the `nRF Connect for Mobile`_ application from the corresponding application store. - The |NCS| build system performs the following steps automatically: +.. _nrf70_gs_installing_sample: - a. Build the NSPE firmware image as a regular |NCS| application. - #. Build an SPE firmware image (with TF-M). - #. Merge the output image binaries. - #. Optionally, build a bootloader image (MCUboot). - .. note:: - Depending on the TF-M configuration, an application DTS overlay can be required to adjust the NSPE image flash memory partition and SRAM starting address and sizes. +Programming the sample +********************** -#. Build the application firmware for the network core using the ``nrf7002dk_nrf5340_cpunet`` build target. +You must program and run a precompiled version of the :ref:`wifi_scan_sample` sample on your development kit to test the functions. +Download the precompiled version of the sample from the `nRF7002 DK Downloads`_ page. +After downloading the zip archive, extract it to a folder of your choice. +The archive contains the HEX file used to program the sample to your DK. -Building the secure firmware using |NCS| -"""""""""""""""""""""""""""""""""""""""" +To program the precompiled sample to your development kit, complete the following steps: -If you want to use |NCS| to build the firmware images with CMSE enabled, but without TF-M, complete the following steps: +1. Open the Programmer app. +#. Connect the nRF7002 DK to the computer with a micro-USB cable and turn on the DK. -1. Build the |NCS| application binary for SPE for the application core using the ``nrf7002dk_nrf5340_cpuapp`` build target. + **LED 5** starts blinking. - Also set :kconfig:option:`CONFIG_TRUSTED_EXECUTION_SECURE` to ``y`` and :kconfig:option:`CONFIG_BUILD_WITH_TFM` to ``n`` in the application project configuration file. -#. Build the |NCS| application binary for NSPE for the application core using the ``nrf7002dk_nrf5340_cpuapp_ns`` build target. -#. Merge the two binaries. -#. Build the application firmware for the network core using the ``nrf7002dk_nrf5340_cpunet`` build target. +#. Click **SELECT DEVICE** and select the DK from the drop-down list. -When building application with SPE and NSPE for the nRF5340 application core, the SPE image must set the IDAU (SPU) configuration to allow non-secure access to all CPU resources used by the application firmware in NSPE. -SPU configuration must be applied before jumping to the application in NSPE. + .. figure:: ../nrf70/images/nRF7002_programmer_select_device.png + :alt: Programmer - Select Device -Building application without CMSE -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Programmer - Select Device -Build the |NCS| application as described in :ref:`gs_programming`, using the ``nrf7002dk_nrf5340_cpuapp`` build target for the firmware running on the nRF5340 application core and the ``nrf7002dk_nrf5340_cpunet`` build target for the firmware running on the nRF5340 network core. + The drop-down text changes to the type of the selected device, with its SEGGER ID below the name. + The **Device Memory Layout** section also changes its name to the device name, and indicates that the device is connected. + If the **Auto read memory** option is selected in the **DEVICE** section of the side panel, the memory layout will update. + If it is not selected and you wish to see the memory layout, click :guilabel:`Read` in the **DEVICE** section of the side panel. -Programming the firmware to the DK -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Click :guilabel:`Add file` in the **FILE** section, and select **Browse**. +#. Navigate to where you extracted the HEX file and select it. +#. Click the :guilabel:`Erase & write` button in the **DEVICE** section to program the DK. -Follow the instructions in the :ref:`gs_programming` page to build and flash applications. + Do not unplug or turn off the DK during this process. .. note:: - To flash and debug applications on the nRF7002 DK, you must use the `nRF Command Line Tools`_ version 10.12.0 or above. + If you experience any problems during the process, press ``Ctrl+R`` (``command+R`` on macOS) to restart the Programmer app, and try again. -Debugging -^^^^^^^^^ +After you have programmed the sample to the DK, you can connect to it and test the functions. -See the :ref:`testing` page for information about debugging. +.. _nrf70_gs_connecting: +Connecting to the sample +************************ -Testing the LEDs and buttons in the nRF7002 DK ----------------------------------------------- +You can connect to the sample on the nRF7002 DK with a terminal emulator on your computer using :term:`Universal Asynchronous Receiver/Transmitter (UART)`. +This allows you to see the logging information the sample outputs. -The following samples allow you to test if the buttons (or switches) and LEDs on the development kit are working properly with |NCS|: +You can use an external UART to USB bridge. +UART communication through the UART to USB CDC ACM bridge is referred to as CDC-UART. -* :zephyr:code-sample:`blinky` -* :zephyr:code-sample:`button` +If you have problems connecting to the sample, restart the DK and start over. -Build and flash the samples to make sure |NCS| is running correctly on your development kit. -For the button and LED definitions, see the :file:`boards/arm/nrf7002dk_nrf5340/nrf5340_cpuapp_common.dts` file. +To connect using CDC-UART, complete the steps listed on the :ref:`test_and_optimize` page for the chosen terminal emulator. -.. _nrf70_gs_shields_expansion_boards: +Once the connection has been established, you can test the sample. -Shields and expansion boards -**************************** +.. _nrf70_gs_testing: -Shields and expansion boards are add-on hardware that can be attached to a development kit or prototyping platform to extend their features and functionalities. +Testing the sample +****************** -nRF7002 EK -========== +You can test the :ref:`wifi_scan_sample` sample on your DK. +The test requires that you have :ref:`connected to the sample ` and have the connected terminal emulator open. -The nRF7002 :term:`Evaluation Kit (EK)` is a versatile evaluation kit in the form of an Arduino shield. -The kit can be used to provide Wi-Fi connectivity and Wi-Fi-based locationing to compatible development or evaluation boards through the nRF7002 Wi-Fi 6 companion IC. +After successful programming of the sample onto the nRF7002 DK, scan results output will be shown in the terminal emulator connected to the sample through CDC-UART. -The nRF7002 EK features the nRF7002 companion IC. -In addition, the shield may be used to emulate the nRF7001 and nRF7000 companion IC variants. - -Overview --------- +.. figure:: ../nrf70/images/nRF7002_scan_sample_output.png + :alt: Scan sample output -The nRF7002 EK (PCA63556) is designed to provide Wi-Fi connectivity and Wi-Fi (SSID) scanning capabilities via the nRF7002 companion IC to a compatible host development board. + Scan sample output -The nRF7002 EK features an Arduino shield form factor and interface connector that allows it to be used with Arduino compatible boards, such as the `nRF52840 DK `_, `nRF5340 DK `_, `nRF9160 DK `_, or `nRF9161 DK `_. -This interface is used to connect the nRF7002 companion device to a host :term:`System on Chip (SoC)`, Microprocessor Unit (MPU), or :term:`Microcontroller Unit (MCU)`. +Building and debugging +********************** -.. figure:: images/nRF7002ek.png - :alt: nRF7002 EK +The nRF5340 application core supports the Armv8-M Security Extension. +Applications built for the ``nrf7002dk_nrf5340_cpuapp`` board boot by default in the secure state. - nRF7002 EK +The nRF5340 network core does not support the Armv8-M Security Extension. +nRF5340 IDAU can configure bus accesses by the nRF5340 network core to have the secure attribute set. +This allows to build and run secure-only applications on the nRF5340 SoC. -Pin assignment for Arduino interface connector ----------------------------------------------- +Building |NCS| applications with Arm TrustZone +============================================== -The Arduino interface of the nRF7002 EK is compatible with the nRF52840 DK, the nRF5340 DK, and an nRF91 Series DK. -The interface connectors are described in the following table: +Applications on nRF5340 can use Cortex-M Security Extensions (CMSE) and separate firmware for the application core between Secure Processing Environment (SPE) and Non-Secure Processing Environment (NSPE). +You can build SPE using either |NCS| or `Trusted Firmware M`_ (TF-M). +You must always build NSPE using |NCS|. -+------------------+-----------------------+----------------------------------+ -| Arduino pin name | nRF7002 Signal | Function | -+==================+=======================+==================================+ -| D0 | IOVDD_EN | Enable power to I/O interface | -+------------------+-----------------------+----------------------------------+ -| D1 | BUCK_EN | Enable power to nRF7002 | -+------------------+-----------------------+----------------------------------+ -| D2 | COEX_STATUS0 | Coexistence status 0 | -+------------------+-----------------------+----------------------------------+ -| D3 | COEX_REQ | Coexistence request from host | -+------------------+-----------------------+----------------------------------+ -| D4 | COEX_GRANT | Coexistence grant to host | -+------------------+-----------------------+----------------------------------+ -| D5 | SW_CTRL0 | Switch control 0 | -+------------------+-----------------------+----------------------------------+ -| D6 | COEX_STATUS1 | Coexistence status 1 | -+------------------+-----------------------+----------------------------------+ -| D7 | HOST_IRQ | Interrupt request to host | -+------------------+-----------------------+----------------------------------+ -| D8 | DATA2 | QSPI data line 2 | -+------------------+-----------------------+----------------------------------+ -| D9 | DATA3 | QSPI data line 3 | -+------------------+-----------------------+----------------------------------+ -| D10 | SS | Slave select | -+------------------+-----------------------+----------------------------------+ -| D11 | MISO/DATA1 | QSPI/SPI Data line 1/ Slave Out | -+------------------+-----------------------+----------------------------------+ -| D12 | MOSI/DATA0 | QSPI/SPI Data line 0/ Slave In | -+------------------+-----------------------+----------------------------------+ -| D13 | CLK | QSPI/SPI Clock | -+------------------+-----------------------+----------------------------------+ -| GND | GND | Ground | -+------------------+-----------------------+----------------------------------+ -| AREF | N.C. | Not used | -+------------------+-----------------------+----------------------------------+ -| SDA | N.C. | Not used | -+------------------+-----------------------+----------------------------------+ -| SCL | N.C. | Not used | -+------------------+-----------------------+----------------------------------+ +For information about Cortex-M Security Extensions (CMSE) and the difference between the two environments, see :ref:`app_boards_spe_nspe`. -Programming ------------ +.. note:: + By default, SPE for the nRF5340 application core is built using TF-M. -To add support for the nRF7002 EK on an application running on a compatible host development board, the ``SHIELD`` setting must be specified. +Building the firmware with TF-M +------------------------------- -To add support for the nRF7002 EK and the nRF7002 IC, set ``-DSHIELD=nrf7002ek`` when you invoke ``west build`` or ``cmake`` in your |NCS| application. -To emulate support for the nRF7001 or nRF7000 ICs, specify ``-DSHIELD=nrf7002ek_nrf7001`` or ``-DSHIELD=nrf7002ek_nrf7000``, respectively. +If you want to use |NCS| to build the firmware image separated in SPE with TF-M and NSPE, complete the following steps: -Alternatively, add the shield in the project's :file:`CMakeLists.txt` file, specifying the below settings, depending on which IC is to be used: +1. Build the |NCS| application for the application core using the ``nrf7002dk_nrf5340_cpuapp_ns`` build target. -.. code-block:: console + To invoke the building of TF-M, the |NCS| build system requires the Kconfig option :kconfig:option:`CONFIG_BUILD_WITH_TFM` to be enabled, which is set by default when building |NCS| as an application that supports both NSPE and SPE. - set(SHIELD nrf7002ek) + The |NCS| build system performs the following steps automatically: -.. code-block:: console + a. Build the NSPE firmware image as a regular |NCS| application. + #. Build an SPE firmware image (with TF-M). + #. Merge the output image binaries. + #. Optionally, build a bootloader image (MCUboot). - set(SHIELD nrf7002ek_nrf7001) + .. note:: + Depending on the TF-M configuration, an application DTS overlay can be required to adjust the NSPE image flash memory partition and SRAM starting address and sizes. -.. code-block:: console +#. Build the application firmware for the network core using the ``nrf7002dk_nrf5340_cpunet`` build target. - set(SHIELD nrf7002ek_nrf7000) +Building application without CMSE +================================= -To build with the |nRFVSC|, specify ``-DSHIELD=nrf7002ek`` in the **Extra CMake arguments** field. -See :ref:`cmake_options` for instructions on how to provide CMake options. +Build the |NCS| application as described in :ref:`building`, using the ``nrf7002dk_nrf5340_cpuapp`` build target for the firmware running on the nRF5340 application core and the ``nrf7002dk_nrf5340_cpunet`` build target for the firmware running on the nRF5340 network core. -To build for the nRF7002 EK and the nRF7002 IC with nRF5340 DK, use the ``nrf5340dk_nrf5340_cpuapp`` build target with the CMake ``SHIELD`` variable set to ``nrf7002ek``. -For example, you can use the following command when building on the command line: +Programming the firmware to the DK +================================== -.. code-block:: console +Follow the instructions in the :ref:`building` page to build and the :ref:`programming` page to program applications. - west build -b nrf5340dk_nrf5340_cpuapp -- -DSHIELD=nrf7002ek +.. note:: + To flash and debug applications on the nRF7002 DK, you must use the `nRF Command Line Tools`_ version 10.12.0 or above. -To build for the nRF7002 EK and the nRF7001 or nRF7000 ICs, you can use the corresponding shield name in the above command. +Debugging +========= -nRF7002 EB -========== +See the :ref:`testing` page for information about debugging. -The nRF7002 :term:`Expansion Board (EB)` can be used to provide Wi-Fi connectivity to compatible development or evaluation boards through the nRF7002 Wi-Fi 6 companion IC. +Next steps +********** -The nRF7002 EB has a :term:`Printed Circuit Board (PCB)` edge connector that can be used with a compatible development board such as the Nordic Thingy:53, an IoT prototyping platform from Nordic Semiconductor. -There are also castellated holes on the side of the board that allow the EB to be used as a breakout board that can be soldered to other PCB assemblies. +You have now completed getting started with the nRF7002 DK. +See the following links for where to go next: -Overview --------- - -The nRF7002 EB (PCA63561) features a PCB edge connector and castellated holes to provide Wi-Fi connectivity through the nRF7002 companion IC. - -The PCB edge connector is used to provide Wi-Fi connectivity to a development board with a compatible connector such as the Nordic Thingy:53, where it connects nRF7002 to nRF5340, which acts as a host. -The EB can also be used to provide Wi-Fi capabilities to develop Wi-Fi applications with another System on Chip (SoC), MPU, or MCU host by using the castellated edge holes on the sides of the board. - -.. figure:: images/nRF7002eb.png - :alt: nRF7002 EB - - nRF7002 EB - -Pin assignment for PCB edge connector -------------------------------------- - -The pinout of the PCB edge connector is shown in the following table. - -+------------------+-----------------------+-----------------------------------------------+ -| Pin number | Signal | Function | -+==================+=======================+===============================================+ -| 1 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 2 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 3 | VIO | IO supply voltage | -+------------------+-----------------------+-----------------------------------------------+ -| 4 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 5 | ST0 | Coexistence Interface Status/Priority signal | -+------------------+-----------------------+-----------------------------------------------+ -| 6 | REQ | Coexistence Interface Request signal | -+------------------+-----------------------+-----------------------------------------------+ -| 7 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 8 | CLK | SPI Clock signal | -+------------------+-----------------------+-----------------------------------------------+ -| 9 | EN | Power Enable signal | -+------------------+-----------------------+-----------------------------------------------+ -| 10 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 11 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 12 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 13 | N.C. | Not used | -+------------------+-----------------------+-----------------------------------------------+ -| 14 | VBAT | Supply voltage | -+------------------+-----------------------+-----------------------------------------------+ -| 15 | GRT | Coexistence Interface Grant signal | -+------------------+-----------------------+-----------------------------------------------+ -| 16 | D0 | SPI MOSI signal | -+------------------+-----------------------+-----------------------------------------------+ -| 17 | D1 | SPI MISO signal | -+------------------+-----------------------+-----------------------------------------------+ -| 18 | CS | SPI Chip Select signal | -+------------------+-----------------------+-----------------------------------------------+ -| 19 | IRQ | Host Interrupt signal | -+------------------+-----------------------+-----------------------------------------------+ -| 20 | GND | Ground | -+------------------+-----------------------+-----------------------------------------------+ - -Castellated edge holes --------------------------- - -Castellated edge holes on the sides of the board connects the nRF7002 EB to the nRF7002 companion IC. -The following figure and table show the pinout for the nRF7002 EB. - -.. figure:: images/nRF7002eb_Castellated_edge.png - :alt: Castellated edge hole numbering - - Castellated edge hole numbering - -+------------------+-----------------------+------------------------------------------------+ -| Pin number | Signal | Function | -+==================+=======================+================================================+ -| 1 | CLK | QSPI Clock/SPI Clock signal | -+------------------+-----------------------+------------------------------------------------+ -| 2 | SS | QSPI Slave Select/SPI Chip Select signal | -+------------------+-----------------------+------------------------------------------------+ -| 3 | D0 | QSPI DATA0/SPI_MOSI signal | -+------------------+-----------------------+------------------------------------------------+ -| 4 | D1 | QSPI DATA1/ SPI_MISO signal | -+------------------+-----------------------+------------------------------------------------+ -| 5 | D2 | QSPI DATA2 signal | -+------------------+-----------------------+------------------------------------------------+ -| 6 | D3 | QSPI DATA3 signal | -+------------------+-----------------------+------------------------------------------------+ -| 7 | CT0 | SW_CTRL0 (not supported on the nRF7002 EB) | -+------------------+-----------------------+------------------------------------------------+ -| 8 | ST1 | SW_CTRL1 | -+------------------+-----------------------+------------------------------------------------+ -| 9 | GND | Ground | -+------------------+-----------------------+------------------------------------------------+ -| 10 | VBAT | Supply voltage | -+------------------+-----------------------+------------------------------------------------+ -| 11 | GND | Ground | -+------------------+-----------------------+------------------------------------------------+ -| 12 | VIO | IO supply voltage | -+------------------+-----------------------+------------------------------------------------+ -| 13 | ST0 | Coexistence Interface Status/Priority signal | -+------------------+-----------------------+------------------------------------------------+ -| 14 | EN | Power Enable signal | -+------------------+-----------------------+------------------------------------------------+ -| 15 | REQ | Coexistence Interface Request signal | -+------------------+-----------------------+------------------------------------------------+ -| 16 | GRT | Coexistence Interface Grant signal | -+------------------+-----------------------+------------------------------------------------+ -| 17 | IRQ | Host Interrupt signal | -+------------------+-----------------------+------------------------------------------------+ -| 18 | GND | Ground | -+------------------+-----------------------+------------------------------------------------+ - -Building --------- - -To build for the nRF7002 EB with Thingy:53, use the ``thingy53_nrf5340_cpuapp`` build target with the CMake ``SHIELD`` variable set to ``nrf7002eb``. -For example, you can use the following command when building on the command line: - -.. code-block:: console - - west build -b thingy53_nrf5340_cpuapp -- -DSHIELD=nrf7002eb - -To build for a custom target, set ``-DSHIELD=nrf7002eb`` when you invoke ``west build`` or ``cmake`` in your |NCS| application. - -Alternatively, add the shield in the project's :file:`CMakeLists.txt` file by using the following command: - -.. code-block:: console - - set(SHIELD nrf7002eb) - -To build with the |nRFVSC|, specify ``-DSHIELD=nrf7002eb`` in the **Extra Cmake arguments** field. -See :ref:`cmake_options` for instructions on how to provide CMake options. - -References -========== - -* `nRF70 Series product page`_ -* `nRF70 Series hardware documentation`_ -* `nRF7002 Product Specification`_ -* `nRF7001 Product Specification`_ +* :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. +* :ref:`ug_nrf70_developing` documentation for more advanced topics related to the nRF70 Series. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_programmer_select_device.png b/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_programmer_select_device.png new file mode 100644 index 00000000000..f4680d97ac7 Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_programmer_select_device.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_scan_sample_output.png b/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_scan_sample_output.png new file mode 100644 index 00000000000..b88bc906add Binary files /dev/null and b/doc/nrf/device_guides/working_with_nrf/nrf70/images/nRF7002_scan_sample_output.png differ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002eb_gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002eb_gs.rst new file mode 100644 index 00000000000..fba6aaac564 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002eb_gs.rst @@ -0,0 +1,202 @@ +.. _ug_nrf7002eb_gs: + +Getting started with nRF7002 EB +############################### + +.. contents:: + :local: + :depth: 4 + +This section gets you started with your nRF7002 :term:`Expansion Board (EB)` using the |NCS|. + +The nRF7002 EB can be used to provide Wi-Fi® connectivity to compatible development or evaluation boards through the nRF7002 Wi-Fi 6 companion IC. + +The nRF7002 EB has a :term:`Printed Circuit Board (PCB)` edge connector that can be used with a compatible development board such as the Nordic Thingy:53, an IoT prototyping platform from Nordic Semiconductor. +There are also castellated holes on the side of the board that allow the EB to be used as a breakout board that can be soldered to other PCB assemblies. + +If this is your first time developing with a Nordic Semiconductor DK, read the appropriate getting started tutorial first: + +* :ref:`ug_nrf7002_gs` +* :ref:`ug_thingy53_gs` +* :ref:`ug_thingy53` + +Overview +******** + +The nRF7002 EB (PCA63561) features a PCB edge connector and castellated holes to provide Wi-Fi connectivity through the nRF7002 companion IC. + +The PCB edge connector is used to provide Wi-Fi connectivity to a development board with a compatible connector such as the Nordic Thingy:53, where it connects nRF7002 to nRF5340, which acts as a host. +The EB can also be used to provide Wi-Fi capabilities to develop Wi-Fi applications with another System on Chip (SoC), MPU, or MCU host by using the castellated edge holes on the sides of the board. + +.. figure:: images/nRF7002eb.png + :alt: nRF7002 EB + + nRF7002 EB + +Pin assignment for PCB edge connector +===================================== + +The pinout of the PCB edge connector is shown in the following table. + ++------------------+-----------------------+-----------------------------------------------+ +| Pin number | Signal | Function | ++==================+=======================+===============================================+ +| 1 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 2 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 3 | VIO | IO supply voltage | ++------------------+-----------------------+-----------------------------------------------+ +| 4 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 5 | ST0 | Coexistence Interface Status/Priority signal | ++------------------+-----------------------+-----------------------------------------------+ +| 6 | REQ | Coexistence Interface Request signal | ++------------------+-----------------------+-----------------------------------------------+ +| 7 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 8 | CLK | SPI Clock signal | ++------------------+-----------------------+-----------------------------------------------+ +| 9 | EN | Power Enable signal | ++------------------+-----------------------+-----------------------------------------------+ +| 10 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 11 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 12 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 13 | N.C. | Not used | ++------------------+-----------------------+-----------------------------------------------+ +| 14 | VBAT | Supply voltage | ++------------------+-----------------------+-----------------------------------------------+ +| 15 | GRT | Coexistence Interface Grant signal | ++------------------+-----------------------+-----------------------------------------------+ +| 16 | D0 | SPI MOSI signal | ++------------------+-----------------------+-----------------------------------------------+ +| 17 | D1 | SPI MISO signal | ++------------------+-----------------------+-----------------------------------------------+ +| 18 | CS | SPI Chip Select signal | ++------------------+-----------------------+-----------------------------------------------+ +| 19 | IRQ | Host Interrupt signal | ++------------------+-----------------------+-----------------------------------------------+ +| 20 | GND | Ground | ++------------------+-----------------------+-----------------------------------------------+ + +Castellated edge holes +====================== + +Castellated edge holes on the sides of the board connects the nRF7002 EB to the nRF7002 companion IC. +The following figure and table show the pinout for the nRF7002 EB. + +.. figure:: images/nRF7002eb_Castellated_edge.png + :alt: Castellated edge hole numbering + + Castellated edge hole numbering + ++------------------+-----------------------+------------------------------------------------+ +| Pin number | Signal | Function | ++==================+=======================+================================================+ +| 1 | CLK | QSPI Clock/SPI Clock signal | ++------------------+-----------------------+------------------------------------------------+ +| 2 | SS | QSPI Slave Select/SPI Chip Select signal | ++------------------+-----------------------+------------------------------------------------+ +| 3 | D0 | QSPI DATA0/SPI_MOSI signal | ++------------------+-----------------------+------------------------------------------------+ +| 4 | D1 | QSPI DATA1/ SPI_MISO signal | ++------------------+-----------------------+------------------------------------------------+ +| 5 | D2 | QSPI DATA2 signal | ++------------------+-----------------------+------------------------------------------------+ +| 6 | D3 | QSPI DATA3 signal | ++------------------+-----------------------+------------------------------------------------+ +| 7 | CT0 | SW_CTRL0 (not supported on the nRF7002 EB) | ++------------------+-----------------------+------------------------------------------------+ +| 8 | ST1 | SW_CTRL1 | ++------------------+-----------------------+------------------------------------------------+ +| 9 | GND | Ground | ++------------------+-----------------------+------------------------------------------------+ +| 10 | VBAT | Supply voltage | ++------------------+-----------------------+------------------------------------------------+ +| 11 | GND | Ground | ++------------------+-----------------------+------------------------------------------------+ +| 12 | VIO | IO supply voltage | ++------------------+-----------------------+------------------------------------------------+ +| 13 | ST0 | Coexistence Interface Status/Priority signal | ++------------------+-----------------------+------------------------------------------------+ +| 14 | EN | Power Enable signal | ++------------------+-----------------------+------------------------------------------------+ +| 15 | REQ | Coexistence Interface Request signal | ++------------------+-----------------------+------------------------------------------------+ +| 16 | GRT | Coexistence Interface Grant signal | ++------------------+-----------------------+------------------------------------------------+ +| 17 | IRQ | Host Interrupt signal | ++------------------+-----------------------+------------------------------------------------+ +| 18 | GND | Ground | ++------------------+-----------------------+------------------------------------------------+ + +Minimum requirements +******************** + +Make sure you have all the required hardware and that your computer and mobile device both have one of the supported operating systems. + +Hardware +======== + +* Nordic Thingy:53 +* nRF7002 EB +* A suitable battery +* Micro-USB 2.0 cable +* USB-C charger +* Jumper wires + +Software +======== + +On your computer, one of the following operating systems: + +* Microsoft Windows +* macOS +* Ubuntu Linux + +|Supported OS| + +.. _nrf7002eb_gs_installing_software: + +Installing the required software +******************************** + +Install `nRF Connect for Desktop`_. +After installing and starting the application, install the Programmer app. + +.. _nrf7002eb_gs_building_programming: + +Building and programming +************************ + +To build for the nRF7002 EB with Thingy:53, use the ``thingy53_nrf5340_cpuapp`` build target with the CMake ``SHIELD`` variable set to ``nrf7002eb``. +For example, you can use the following command when building on the command line: + +.. code-block:: console + + west build -b thingy53_nrf5340_cpuapp -- -DSHIELD=nrf7002eb + +To build for a custom target, set ``-DSHIELD=nrf7002eb`` when you invoke ``west build`` or ``cmake`` in your |NCS| application. + +Alternatively, add the shield in the project's :file:`CMakeLists.txt` file by using the following command: + +.. code-block:: console + + set(SHIELD nrf7002eb) + +To build with the |nRFVSC|, specify ``-DSHIELD=nrf7002eb`` in the **Extra Cmake arguments** field. +See :ref:`cmake_options` for instructions on how to provide CMake options. + +Next steps +********** + +You have now completed getting started with the nRF7002 EB. +See the following links for where to go next: + +* :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. +* The EB `User Guide `_ for detailed information related to the nRF7002 EB. +* `nRF70 Series product page`_ +* `nRF70 Series hardware documentation`_ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002ek_gs.rst b/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002ek_gs.rst new file mode 100644 index 00000000000..e8a06298144 --- /dev/null +++ b/doc/nrf/device_guides/working_with_nrf/nrf70/nrf7002ek_gs.rst @@ -0,0 +1,178 @@ +.. _ug_nrf7002ek_gs: + +Getting started with nRF7002 EK +############################### + +.. contents:: + :local: + :depth: 4 + +This section gets you started with your nRF7002 :term:`Evaluation Kit (EK)` using the |NCS|. + +The nRF7002 EK is a versatile evaluation kit in the form of an Arduino shield. +The kit can be used to provide Wi-Fi® connectivity and Wi-Fi-based locationing to compatible development or evaluation boards through the nRF7002 Wi-Fi 6 companion IC. + +The nRF7002 EK features the nRF7002 companion IC. +In addition, the shield may be used to emulate the nRF7001 and nRF7000 companion IC variants. + +If this is your first time developing with a Nordic Semiconductor DK, read the appropriate getting started tutorial first: + +* :ref:`ug_nrf7002_gs` +* :ref:`ug_nrf52_gs` +* :ref:`ug_nrf5340_gs` +* :ref:`ug_nrf9160_gs` + +Overview +******** + +The nRF7002 EK (PCA63556) is designed to provide Wi-Fi connectivity and Wi-Fi (SSID) scanning capabilities through the nRF7002 companion IC to a compatible host development board. + +The nRF7002 EK features an Arduino shield form factor and interface connector that allows it to be used with Arduino compatible boards, such as the `nRF52840 DK `_, `nRF5340 DK `_, `nRF9160 DK `_, or `nRF9161 DK `_. +This interface is used to connect the nRF7002 companion device to a host :term:`System on Chip (SoC)`, Microprocessor Unit (MPU), or :term:`Microcontroller Unit (MCU)`. + +.. figure:: images/nRF7002ek.png + :alt: nRF7002 EK + + nRF7002 EK + +Pin assignment for Arduino interface connector +============================================== + +The Arduino interface of the nRF7002 EK is compatible with the nRF52840 DK, the nRF5340 DK, and an nRF91 Series DK. +The interface connectors are described in the following table: + ++----------------------+-----------------------+----------------------------------+ +| Arduino pin name | nRF7002 Signal | Function | ++======================+=======================+==================================+ +| **D0** | IOVDD_EN | Enable power to I/O interface | ++----------------------+-----------------------+----------------------------------+ +| **D1** | BUCK_EN | Enable power to nRF7002 | ++----------------------+-----------------------+----------------------------------+ +| **D2** | COEX_STATUS0 | Coexistence status 0 | ++----------------------+-----------------------+----------------------------------+ +| **D3** | COEX_REQ | Coexistence request from host | ++----------------------+-----------------------+----------------------------------+ +| **D4** | COEX_GRANT | Coexistence grant to host | ++----------------------+-----------------------+----------------------------------+ +| **D5** | SW_CTRL0 | Switch control 0 | ++----------------------+-----------------------+----------------------------------+ +| **D6** | COEX_STATUS1 | Coexistence status 1 | ++----------------------+-----------------------+----------------------------------+ +| **D7** | HOST_IRQ | Interrupt request to host | ++----------------------+-----------------------+----------------------------------+ +| **D8** | DATA2 | QSPI data line 2 | ++----------------------+-----------------------+----------------------------------+ +| **D9** | DATA3 | QSPI data line 3 | ++----------------------+-----------------------+----------------------------------+ +| **D10** | SS | Slave select | ++----------------------+-----------------------+----------------------------------+ +| **D11** | MISO/DATA1 | QSPI/SPI Data line 1/ Slave Out | ++----------------------+-----------------------+----------------------------------+ +| **D12** | MOSI/DATA0 | QSPI/SPI Data line 0/ Slave In | ++----------------------+-----------------------+----------------------------------+ +| **D13** | CLK | QSPI/SPI Clock | ++----------------------+-----------------------+----------------------------------+ +| **GND** | GND | Ground | ++----------------------+-----------------------+----------------------------------+ +| **AREF** | N.C. | Not used | ++----------------------+-----------------------+----------------------------------+ +| **SDA** | N.C. | Not used | ++----------------------+-----------------------+----------------------------------+ +| **SCL** | N.C. | Not used | ++----------------------+-----------------------+----------------------------------+ + +.. note:: + ``UART1`` cannot be used and must be disabled on the nRF9160 DK, as ``UART1`` ``RXD`` and ``TXD`` conflict with pins **P0.00** and **P0.01** (Arduino pins **D0** and **D1**). + These correspond to the IOVDD-CTRL-GPIOS and BUCKEN-GPIOS signals in the nRF7002 EK, respectively. + + For an nRF7002 EK connected to an nRF9160 DK, you can find example overlays at the following paths: + + * :file:`sdk-nrf/boards/shields/nrf7002ek/boards/nrf9160dk_nrf9160_ns.overlay` + * :file:`sdk-nrf/samples/cellular/lwm2m_client/boards/nrf9160dk_with_nrf7002ek.overlay` + +Minimum requirements +******************** + +Make sure you have all the required hardware and that your computer and mobile device both have one of the supported operating systems. + +Hardware +======== + +* One of the following development kits: + + * nRF52840 DK + * nRF5340 DK + * nRF9160 DK + * nRF9161 DK + +* nRF7002 EK +* A suitable battery +* Micro-USB 2.0 cable +* USB-C charger +* Jumper wires + +Software +======== + +On your computer, one of the following operating systems: + +* Microsoft Windows +* macOS +* Ubuntu Linux + +|Supported OS| + +.. _nrf7002ek_gs_installing_software: + +Installing the required software +******************************** + +Install `nRF Connect for Desktop`_. +After installing and starting the application, install the Programmer app. + +.. _nrf7002ek_gs_building_programming: + +Building and programming +************************ + +To add support for the nRF7002 EK on an application running on a compatible host development board, the ``SHIELD`` setting must be specified. + +To add support for the nRF7002 EK and the nRF7002 IC, set ``-DSHIELD=nrf7002ek`` when you invoke ``west build`` or ``cmake`` in your |NCS| application. +To emulate support for the nRF7001 or nRF7000 ICs, specify ``-DSHIELD=nrf7002ek_nrf7001`` or ``-DSHIELD=nrf7002ek_nrf7000``, respectively. + +Alternatively, add the shield in the project's :file:`CMakeLists.txt` file, specifying the below settings, depending on which IC is to be used: + +.. code-block:: console + + set(SHIELD nrf7002ek) + +.. code-block:: console + + set(SHIELD nrf7002ek_nrf7001) + +.. code-block:: console + + set(SHIELD nrf7002ek_nrf7000) + +To build with the |nRFVSC|, specify ``-DSHIELD=nrf7002ek`` in the **Extra CMake arguments** field. +See :ref:`cmake_options` for instructions on how to provide CMake options. + +To build for the nRF7002 EK and the nRF7002 IC with nRF5340 DK, use the ``nrf5340dk_nrf5340_cpuapp`` build target with the CMake ``SHIELD`` variable set to ``nrf7002ek``. +For example, you can use the following command when building on the command line: + +.. code-block:: console + + west build -b nrf5340dk_nrf5340_cpuapp -- -DSHIELD=nrf7002ek + +To build for the nRF7002 EK and the nRF7001 or nRF7000 ICs, you can use the corresponding shield name in the above command. + +Next steps +********** + +You have now completed getting started with the nRF7002 EK. +See the following links for where to go next: + +* :ref:`installation` and :ref:`configuration_and_build` documentation to install the |NCS| and learn more about its development environment. +* The EK `User Guide `_ for detailed information related to the nRF7002 EK. +* `nRF70 Series product page`_ +* `nRF70 Series hardware documentation`_ diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9160.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9160.rst index a8c1e3e6abc..cfa9438453b 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9160.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9160.rst @@ -20,6 +20,7 @@ Board controller The nRF9160 DK contains an nRF52840 SoC that is used to route some of the nRF9160 SiP pins to different components on the DK, such as LEDs and buttons, and to specific pins of the nRF52840 SoC itself. For a complete list of all the routing options available, see the `nRF9160 DK board control section in the nRF9160 DK User Guide`_. +Make sure to select the correct controller before you program the application to your development kit. The nRF52840 SoC on the DK comes preprogrammed with a firmware. If you need to restore the original firmware at some point, download the nRF9160 DK board controller firmware from the `nRF9160 DK downloads`_ page. @@ -230,7 +231,7 @@ Modem firmware .. tip:: For a more compact nRF Cloud firmware application, you can build and install the :ref:`nrf_cloud_multi_service` sample. - See :ref:`gs_programming` for details on building a firmware sample application. + See :ref:`building` for details on building a firmware sample application. The :file:`CONTENTS.txt` file in the extracted folder contains the location and names of the different firmware images. @@ -358,7 +359,7 @@ Building and programming You can program applications and samples on the nRF9160 DK after obtaining the corresponding firmware images. .. note:: - When you update the application firmware on an nRF9160 DK, make sure the modem firmware and application firmware are compatible versions. + When you update the application firmware on an nRF9160 DK, make sure that the modem firmware and application firmware are compatible versions. To program applications using the Programmer app from `nRF Connect for Desktop`_, follow the instructions in :ref:`nrf9160_updating_fw_application`. @@ -507,7 +508,7 @@ Enable the following Kconfig options by setting it to ``y`` in your project conf * :kconfig:option:`CONFIG_SPI_NOR_SFDP_DEVICETREE` * :kconfig:option:`CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK` -To automatically include the devicetree overlay with the external flash, specify the board revision parameter when :ref:`gs_programming`. +To automatically include the devicetree overlay with the external flash, specify the board revision parameter when :ref:`building`. The board revision is printed on the label of your DK, just below the PCA number. Then add the following relevant devicetree blocks to the application`s devicetree overlay file, depending on your application`s needs: @@ -540,7 +541,7 @@ If your application was built using the |NCS|, you must define partitions using The built-in partition definitions can be found in the :file:`nrf/subsys/partition_manager` folder, and the file names start with ``pm.yml``. The files which have ``external_flash`` as their region will have support for storing partitions in the external flash. You can also find the configuration option required to place the partition in the external flash region in those files. -For example, the :file:`pm.yml.pgps` file has an option (:kconfig:option:`CONFIG_PM_PARTITION_REGION_PGPS_EXTERNAL`) to place the PGPS partition in external flash: +For example, the :file:`pm.yml.pgps` file has an option (:kconfig:option:`CONFIG_PM_PARTITION_REGION_PGPS_EXTERNAL`) to place the P-GPS partition in external flash: .. code-block:: c @@ -553,8 +554,6 @@ For example, the :file:`pm.yml.pgps` file has an option (:kconfig:option:`CONFIG It is also possible to change the size of the partition with :kconfig:option:`CONFIG_NRF_CLOUD_PGPS_PARTITION_SIZE`. -.. _nrf9160_ug_drivs_libs_samples: - Available drivers, libraries, and samples ***************************************** diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9161.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9161.rst index 9492f062a1b..b3fc4b6f898 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9161.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf9161.rst @@ -23,7 +23,9 @@ The nRF9161 DK contains an nRF5340 Interface MCU (IMCU), which acts both as an o The board controller controls signal switches on the nRF9161 DK and can be used to route the nRF9161 SiP pins to different components on the DK, such as pin headers, external memory, a SIM card or eSIM. For a complete list of configuration options available, see the nRF9161 DK board control section in the nRF9161 DK User Guide. -The nRF5340 IMCU comes preprogrammed with J-Link Segger OB and board controller firmware. +The nRF5340 IMCU comes preprogrammed with J-Link SEGGER OB and board controller firmware. +If you want to change the default configuration of the DK, you can use the Board Configurator app in `nRF Connect for Desktop`_ . +See the `nRF Connect Board Configurator`_ documentation for instructions on how to change the configuration of the DK. .. _nrf9161_ug_updating_cloud_certificate: @@ -37,6 +39,7 @@ Updating the nRF Cloud certificate :end-before: dk_update_cloud_cer_end .. _downloading_cloud_certificate_nRF9161: +.. _downloading_cloud_certificate_nRF91x1: Downloading the nRF Cloud certificate for the |DK| ================================================== diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_features.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_features.rst index 635bc3a8d3b..b7ad4edccb2 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_features.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_features.rst @@ -10,11 +10,6 @@ Features of nRF91 Series The nRF91 Series SiPs integrate an application MCU, a full LTE modem, an RF front end, and power management. With built-in GNSS support, it is a great choice for asset tracking applications. -For more details on the SiPs, see the following guides: - -* nRF9161 - `nRF9161 product website`_ and the `nRF9161 Product Specification`_ -* nRF9160 - `nRF9160 product website`_ and the `nRF9160 Product Specification`_ - The following figure illustrates the conceptual layout when targeting an nRF91 Series Cortex-M33 application MCU with TrustZone: .. figure:: images/nrf91_ug_overview.svg @@ -22,36 +17,6 @@ The following figure illustrates the conceptual layout when targeting an nRF91 S Overview of nRF91 application architecture -Supported boards -**************** - -Devices in the nRF91 Series are supported by the following boards in the `Zephyr`_ open source project and in |NCS|. - - -.. list-table:: - :header-rows: 1 - - * - DK or Prototype platform - - PCA number - - Build target - - Documentation - * - :ref:`zephyr:nrf9161dk_nrf9161` - - PCA10153 - - ``nrf9161dk_nrf9161_ns`` - - | `Product Specification `_ - | `User Guide `_ - * - :ref:`zephyr:nrf9160dk_nrf9160` - - PCA10090 - - ``nrf9160dk_nrf9160_ns`` - - | `Product Specification `_ - | :ref:`Getting started ` - | `User Guide `_ - * - Thingy91 - - PCA20035 - - ``thingy91_nrf9160_ns`` - - | :ref:`Getting started ` - | `User Guide `_ - Application MCU *************** @@ -105,8 +70,8 @@ The AT commands are documented in the `nRF91x1 AT Commands Reference Guide`_ an The firmware for the modem is available as a precompiled binary. You can download the firmware from the `nRF9161 product website (compatible downloads)`_ or `nRF9160 product website (compatible downloads)`_, depending on the SiP you are using. -The zip file contains the release notes, and both the full firmware and patches to upgrade from one version to another. -A delta patch can only upgrade the modem firmware from one specific version to another version (for example, v1.2.1 to v1.2.2). +The zip file contains the release notes, and both the full firmware and patches to update from one version to another. +A delta patch can only update the modem firmware from one specific version to another version (for example, v1.2.1 to v1.2.2). If you need to perform a major version update (for example, v1.2.x to v1.3.x), you need an external flash with a minimum size of 4 MB. Different versions of the LTE modem firmware are available, and these versions are certified for the mobile network operators having their own certification programs. @@ -120,13 +85,13 @@ See the `Mobile network operator certifications`_ for more information. .. _nrf91_update_modem_fw: .. _nrf9160_update_modem_fw: -Modem firmware upgrade -====================== +Modem firmware update +===================== There are two ways to update the modem firmware: -Full upgrade - You can use either a wired or a wireless connection to do a full upgrade of the modem firmware: +Full update + You can use either a wired or a wireless connection to do a full update of the modem firmware: * When using a wired connection, you can use either the `nRF Connect Programmer`_, which is part of `nRF Connect for Desktop`_, or the `nRF pynrfjprog`_ Python package. Both methods use the Simple Management Protocol (SMP) to provide an interface over UART, which enables the device to perform the update. @@ -137,16 +102,16 @@ Full upgrade * You can also use the nRF pynrfjprog Python package to perform the update, as long as a custom application image integrating the ``lib_fmfu_mgmt`` subsystem is included in the existing firmware of the device. See the :ref:`fmfu_smp_svr_sample` sample for an example on how to integrate the :ref:`subsystem ` in your custom application. - * When using a wireless connection, the upgrade is applied over-the-air (OTA). + * When using a wireless connection, the update is applied over-the-air (OTA). See :ref:`nrf91_fota` for more information. See :ref:`nrfxlib:nrf_modem_bootloader` for more information on the full firmware updates of modem using :ref:`nrfxlib:nrf_modem`. Delta patches - Delta patches are upgrades that contain only the difference from the last version. + Delta patches are updates that contain only the difference from the last version. See :ref:`nrfxlib:nrf_modem_delta_dfu` for more information on delta firmware updates of modem using :ref:`nrfxlib:nrf_modem`. When applying a delta patch, you must therefore ensure that this patch works with the current firmware version on your device. - Delta patches are applied as firmware over-the-air (FOTA) upgrades. + Delta patches are applied as firmware over-the-air (FOTA) updates. See :ref:`nrf91_fota` for more information. .. _nrf91_ug_band_lock: @@ -172,7 +137,7 @@ The band lock mask allows you to set the bands on which you want the modem to op Each bit in the :kconfig:option:`CONFIG_LTE_LOCK_BAND_MASK` option represents one band. The maximum length of the string is 88 characters (bit string, 88 bits). -For more detailed information, see the `band lock section in the AT Commands reference document`_. +For more detailed information, see the `band lock section in the nRF9160 AT Commands Reference Guide`_ or the `band lock section in the nRF91x1 AT Commands Reference Guide`_, depending on the SiP you are using. .. _nrf91_ug_network_mode: .. _nrf9160_ug_network_mode: @@ -188,17 +153,21 @@ You can change the enabled systems using the :kconfig:option:`CONFIG_LTE_NETWORK When the :ref:`lte_lc_readme` library is not used, the modem starts in LTE-M mode. You can change the system mode and the LTE system mode preference using the ``AT%XSYSTEMMODE`` AT command. -For more detailed information, see the `system mode section in the AT Commands reference document`_. +For more detailed information, see the `system mode section in the nRF9160 AT Commands Reference Guide`_ or the `system mode section in the nRF91x1 AT Commands Reference Guide`_, depending on the SiP you are using. Modem library ************* +.. nrf91_modem_lib_start + The |NCS| applications for the nRF91 Series devices that communicate with the nRF91 Series modem firmware must include the :ref:`nrfxlib:nrf_modem`. The :ref:`nrfxlib:nrf_modem` is released as an OS-independent binary library in the :ref:`nrfxlib` repository and it is integrated into |NCS| through an integration layer, ``nrf_modem_lib``. The Modem library integration layer fulfills the integration requirements of the Modem library in |NCS|. For more information on the integration, see :ref:`nrf_modem_lib_readme`. +.. nrf91_modem_lib_end + .. _modem_trace: Modem trace @@ -212,7 +181,7 @@ To enable the modem traces in the modem and to forward them to the :ref:`modem_t For the :ref:`serial_lte_modem` application and the :ref:`at_client_sample` sample, you must also run ``AT%XMODEMTRACE=1,2`` to manually activate the predefined trace set. You can set the trace level using the AT command ``AT%XMODEMTRACE``. -See `modem trace AT command documentation`_ for more information. +For more information, see the `modem trace activation %XMODEMTRACE`_ section in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. See :ref:`modem_trace_module` for other backend options. If the existing trace backends are not sufficient, it is possible to implement custom trace backends. @@ -221,34 +190,34 @@ For more information on the implementation of a custom trace backend, see :ref:` .. _nrf91_fota: .. _nrf9160_fota: -FOTA upgrades -************* +FOTA updates +************ |fota_upgrades_def| -FOTA upgrades can be used to apply delta patches to the :ref:`lte_modem` firmware, full :ref:`lte_modem` firmware upgrades, and to replace the upgradable bootloader or the application. +FOTA updates can be used to apply delta patches to the :ref:`lte_modem` firmware, full :ref:`lte_modem` firmware updates, and to replace the upgradable bootloader or the application. .. note:: - Even though the Trusted Firmware-M and the application are two individually compiled components, they are treated as a single binary blob in the context of firmware upgrades. + Even though the Trusted Firmware-M and the application are two individually compiled components, they are treated as a single binary blob in the context of firmware updates. Any reference to the application in this section is meant to indicate the application including the Trusted Firmware-M. -To perform a FOTA upgrade, complete the following steps: +To perform a FOTA updates, complete the following steps: -1. Make sure that your application supports FOTA upgrades. +1. Make sure that your application supports FOTA updates. - To download and apply FOTA upgrades, your application must use the :ref:`lib_fota_download` library. - This library determines the type of upgrade by inspecting the header of the firmware and invokes the :ref:`lib_dfu_target` library to apply the firmware upgrade. - In its default configuration, the DFU target library is set to support all the types of FOTA upgrades except full modem firmware upgrades, but you can freely enable or disable the support for specific targets. + To download and apply FOTA updates, your application must use the :ref:`lib_fota_download` library. + This library determines the type of update by inspecting the header of the firmware and invokes the :ref:`lib_dfu_target` library to apply the firmware update. + In its default configuration, the DFU target library is set to support all the types of FOTA updates except full modem firmware updates, but you can freely enable or disable the support for specific targets. In addition, the following requirements apply: * To upgrade the application, you must use :doc:`mcuboot:index-ncs` as the upgradable bootloader (:kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` must be enabled). * If you want to upgrade the upgradable bootloader, you must use the :ref:`bootloader` (:kconfig:option:`CONFIG_SECURE_BOOT must be enabled`). - * If you want to upgrade the modem firmware through modem delta updates, you do not need to use MCUboot or the immutable bootloader, because the modem firmware upgrade is handled by the modem itself. - * If you want to perform a full modem firmware upgrade, an |external_flash_size| is required. + * If you want to update the modem firmware through modem delta updates, you do not need to use MCUboot or the immutable bootloader, because the modem firmware update is handled by the modem itself. + * If you want to perform a full modem firmware update, an |external_flash_size| is required. #. Create a binary file that contains the new image. .. note:: - This step does not apply for upgrades of the modem firmware. + This step does not apply for updates of the modem firmware. You can download delta patches and full binaries of the modem firmware from the `nRF9161 product website (compatible downloads)`_ or `nRF9160 product website (compatible downloads)`_, depending on the SiP you are using. |fota_upgrades_building| @@ -263,10 +232,10 @@ To perform a FOTA upgrade, complete the following steps: The full FOTA procedure depends on where the binary files are hosted for download. -FOTA upgrades using nRF Cloud -============================= +FOTA updates using nRF Cloud +============================ -FOTA upgrades can be managed through a comprehensive management portal on `nRF Cloud`_, either fully hosted on nRF Cloud or accessible from a customer cloud using the `nRF Cloud REST API`_. +FOTA updates can be managed through a comprehensive management portal on `nRF Cloud`_, either fully hosted on nRF Cloud or accessible from a customer cloud using the `nRF Cloud REST API`_. If you are using nRF Cloud, see the `nRF Cloud Getting Started FOTA documentation`_ for instructions. Currently, delta modem firmware FOTA files are available in nRF Cloud under :guilabel:`Firmware Updates` in the :guilabel:`Device Management` tab on the left. @@ -275,10 +244,10 @@ If you intend to obtain FOTA files from nRF Cloud, see the additional requiremen You can upload custom application binaries to nRF Cloud for application FOTA updates. After :ref:`nrf9160_gs_connecting_dk_to_cloud`, you can upload the files to your nRF Cloud account as a bundle after navigating to :guilabel:`Device Management` on the left and clicking :guilabel:`Firmware Updates`. -FOTA upgrades using other cloud services +FOTA updates using other cloud services ======================================== -FOTA upgrades can alternatively be hosted from a customer-developed cloud services such as solutions based on AWS and Azure. +FOTA updates can alternatively be hosted from a customer-developed cloud services such as solutions based on AWS and Azure. If you are uploading the files to an Amazon Web Services Simple Storage Service (AWS S3) bucket, see the :ref:`lib_aws_fota` documentation for instructions. Samples are provided in |NCS| for AWS (:ref:`aws_iot` sample) and Azure (:ref:`azure_iot_hub` sample). @@ -289,12 +258,13 @@ You can hardcode the information in the application, or you can use a functional Samples and applications implementing FOTA ========================================== -* :ref:`http_modem_full_update_sample` sample - performs a full firmware OTA update of the modem. -* :ref:`http_modem_delta_update_sample` sample - performs a delta OTA update of the modem firmware. -* :ref:`http_application_update_sample` sample - performs a basic application FOTA update. -* :ref:`aws_iot` sample - performs a FOTA update using MQTT and HTTP, where the firmware download is triggered through an AWS IoT job. -* :ref:`azure_iot_hub` sample - performs a FOTA update from the Azure IoT Hub. -* :ref:`asset_tracker_v2` application - performs FOTA updates of the application, modem (delta), and boot (if enabled). It also supports nRF Cloud FOTA as well as AWS or Azure FOTA. Only one must be configured at a time. +* :ref:`http_modem_full_update_sample` sample - Performs a full firmware OTA update of the modem. +* :ref:`http_modem_delta_update_sample` sample - Performs a delta OTA update of the modem firmware. +* :ref:`http_application_update_sample` sample - Performs a basic application FOTA update. +* :ref:`aws_iot` sample - Performs a FOTA update using MQTT and HTTP, where the firmware download is triggered through an AWS IoT job. +* :ref:`azure_iot_hub` sample - Performs a FOTA update from the Azure IoT Hub. +* :ref:`asset_tracker_v2` application - Performs FOTA updates of the application, modem (delta), and boot (if enabled). + It also supports nRF Cloud FOTA as well as AWS or Azure FOTA. Only one must be configured at a time. .. _nrf91_ug_gnss: .. _nrf9160_ug_gnss: @@ -351,7 +321,7 @@ Concurrent GNSS and LTE The GNSS operation in an nRF91 Series device is time-multiplexed with the LTE modem. Therefore, the LTE modem must either be completely deactivated or in `RRC idle mode `_ or `Power Saving Mode (PSM)`_ when using the GNSS receiver. -For an nRF9160 SiP, see the `nRF9160 GPS receiver Specification`_ for more information. +For more information, see the `nRF9161 GPS receiver Specification`_ or the `nRF9160 GPS receiver Specification`_, depending on the SiP you are using. Enhancements to GNSS ==================== diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_snippet.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_snippet.rst index 3adfb11f153..7d95b06bc51 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_snippet.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/nrf91_snippet.rst @@ -9,11 +9,34 @@ Snippets for an nRF91 Series device :ref:`snippets` are tailored for tracing on the nRF91 Series devices but can work with other boards as well. -In |NCS|, snippets are used for the following functionalities: +On nRF91 Series devices, snippets are used for the following functionalities: +* Modem tracing with the flash backend * Modem tracing with the UART backend * To activate TF-M logging while having modem traces enabled +.. _nrf91_modem_trace_ext_flash_snippet: + +nRF91 modem traces with flash backend using snippets +==================================================== + +Snippet enables modem tracing, the flash backend, and external flash and configures them to store modem traces to a dedicated partition on the external flash for supported boards. +To change the partition size, the project needs to configure the :kconfig:option:`CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_FLASH_PARTITION_SIZE` Kconfig option. + +The following build targets have support for this snippet: + +* ``nrf9151dk_nrf9151_ns`` +* ``nrf9161dk_nrf9161_ns`` +* ``nrf9160dk_nrf9160_ns`` +* ``nrf9131ek_nrf9131_ns`` + +To enable modem traces with the flash backend, use the following command: + +.. parsed-literal:: + :class: highlight + + west build --board *build target* -S nrf91-modem-trace-ext-flash + .. _nrf91_modem_trace_uart_snippet: nRF91 modem tracing with UART backend using snippets diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91.rst index b983ad7c485..3fb2846539d 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91.rst @@ -93,7 +93,7 @@ LTE Band Lock ************* The modem within Thingy:91 can be configured to use specific LTE bands by using the band lock AT command. -See :ref:`nrf91_ug_band_lock` and the `band lock section in the AT Commands reference document`_ for additional information. +See :ref:`nrf91_ug_band_lock` and the `band lock section in the nRF9160 AT Commands Reference Guide`_ for additional information. The preprogrammed firmware configures the modem to use the bands currently certified on the Thingy:91 hardware. When building the firmware, you can configure which bands must be enabled. diff --git a/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91_gsg.rst b/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91_gsg.rst index b8bda380c2c..a30900d2079 100644 --- a/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91_gsg.rst +++ b/doc/nrf/device_guides/working_with_nrf/nrf91/thingy91_gsg.rst @@ -277,7 +277,7 @@ Adding the Thingy:91 to nRF Cloud ================================= .. |led_cloud_association| replace:: the RGB LED double pulse blinks as white -.. |led_publishing_data| replace:: the RGB LED blinking green +.. |led_publishing_data| replace:: RGB LED blinking green .. |activate_sim_section| replace:: :ref:`thingy91_cloud_activate_sim` .. include:: nrf9160_gs.rst diff --git a/doc/nrf/drivers/eth_rtt.rst b/doc/nrf/drivers/eth_rtt.rst index 8a01c9c42b3..75d10818519 100644 --- a/doc/nrf/drivers/eth_rtt.rst +++ b/doc/nrf/drivers/eth_rtt.rst @@ -42,7 +42,7 @@ The content of this frame is constant and it is available in the driver source c Initialization ************** -You need to define one instance of the device in Devicetree like this: +You need to define one instance of the device in devicetree like this: .. code-block:: devicetree diff --git a/doc/nrf/drivers/sensor_sim.rst b/doc/nrf/drivers/sensor_sim.rst index 0fdb07af7f1..1b5ec56e83d 100644 --- a/doc/nrf/drivers/sensor_sim.rst +++ b/doc/nrf/drivers/sensor_sim.rst @@ -13,7 +13,7 @@ The sensor provides readouts for predefined set of sensor channels and supports Configuration ************* -You can define instances of the sensor simulator on Devicetree like this: +You can define instances of the sensor simulator in devicetree as shown in the following code snippet: .. code-block:: devicetree @@ -22,7 +22,7 @@ You can define instances of the sensor simulator on Devicetree like this: acc-signal = "toggle"; }; -The sensor driver will automatically be built if ``CONFIG_SENSOR=y`` and any of its instances in Devicetree have status set to ``okay``. +The sensor driver will automatically be built if ``CONFIG_SENSOR=y`` and any of its instances in devicetree have status set to ``okay``. Configuration of generated readouts =================================== @@ -30,11 +30,11 @@ Configuration of generated readouts The algorithms used to generate simulated sensor readouts are configurable. The following sensor channels and configuration options are available: -* Ambient temperature (:c:enum:`SENSOR_CHAN_AMBIENT_TEMP`) - The value is generated as the sum of the value of the Devicetree property ``base-temperature`` a pseudo-random number between ``-1`` and ``1``. -* Humidity (:c:enum:`SENSOR_CHAN_HUMIDITY`) - The value is generated as the sum of the value of the Devicetree property ``base-humidity`` and a pseudo-random number between ``-1`` and ``1``. -* Pressure (:c:enum:`SENSOR_CHAN_PRESS`) - The value is generated as the sum of the value of the Devicetree property ``base-pressure`` and a pseudo-random number between ``-1`` and ``1``. +* Ambient temperature (:c:enum:`SENSOR_CHAN_AMBIENT_TEMP`) - The value is generated as the sum of the value of the devicetree property ``base-temperature`` and a pseudo-random number between ``-1`` and ``1``. +* Humidity (:c:enum:`SENSOR_CHAN_HUMIDITY`) - The value is generated as the sum of the value of the devicetree property ``base-humidity`` and a pseudo-random number between ``-1`` and ``1``. +* Pressure (:c:enum:`SENSOR_CHAN_PRESS`) - The value is generated as the sum of the value of the devicetree property ``base-pressure`` and a pseudo-random number between ``-1`` and ``1``. * Acceleration in X, Y, and Z axes (:c:enum:`SENSOR_CHAN_ACCEL_X`, :c:enum:`SENSOR_CHAN_ACCEL_Y`, :c:enum:`SENSOR_CHAN_ACCEL_Z`, for each axis respectively, and :c:enum:`SENSOR_CHAN_ACCEL_XYZ` for all axes at once). - The acceleration is generated depending on the selected Devicetree ``acc-signal`` property: + The acceleration is generated depending on the selected devicetree ``acc-signal`` property: * ``toggle`` - With this choice, the acceleration is toggled on fetch between statically defined values. * ``wave`` - With this choice, the acceleration is generated as value of a periodic wave signal. @@ -48,7 +48,7 @@ Configuration of sensor triggers Use :kconfig:option:`CONFIG_SENSOR_SIM_TRIGGER` to enable the sensor trigger. The simulated sensor supports the :c:enum:`SENSOR_TRIG_DATA_READY` trigger. -You can configure the event that generates the trigger in Devicetree by using the ``trigger-gpios`` or ``trigger-timeout`` options. +You can configure the event that generates the trigger in devicetree by using the ``trigger-gpios`` or ``trigger-timeout`` options. For both triggers, the handler function is called by a dedicated thread. The thread has the following configuration options: diff --git a/doc/nrf/drivers/wifi/nrf700x/nrf700x.rst b/doc/nrf/drivers/wifi/nrf700x/nrf700x.rst index 6373733c092..332f8cf6a3f 100644 --- a/doc/nrf/drivers/wifi/nrf700x/nrf700x.rst +++ b/doc/nrf/drivers/wifi/nrf700x/nrf700x.rst @@ -1,39 +1,39 @@ .. _nrf700x_wifi: -nRF70 Series Wi-Fi driver -######################### +nRF Wi-Fi driver +################ .. contents:: :local: :depth: 2 -This driver implements the Wi-Fi® protocol for the nRF70 FullMAC Series of devices. +The nRF Wi-Fi driver implements the Wi-Fi® protocol for the nRF70 FullMAC Series of devices. FullMAC devices implement the Wi-Fi protocol in the chipset. The driver configures the chipset and transfers the frames to and from the device to the networking stack. -nRF70 Series device is a companion IC and can be used with any Nordic Semiconductor System-on-Chips (SoCs) such as the nRF53 and nRF91 Series SoCs. +nRF70 Series device is a companion IC and can be used with any Nordic Semiconductor System-on-Chips (SoCs), such as the nRF53 and nRF91 Series SoCs. You can enable the driver by using the :kconfig:option:`CONFIG_WIFI_NRF700X` Kconfig option. Architecture ************* -The following figure illustrates the architecture of the nRF70 Series Wi-Fi driver. +The following figure illustrates the architecture of the nRF Wi-Fi driver. .. figure:: /images/nrf700x_wifi_driver.svg - :alt: nRF70 Series Wi-Fi driver block diagram + :alt: nRF Wi-Fi driver block diagram :align: center :figclass: align-center - nRF70 Series Wi-Fi driver architecture overview + nRF Wi-Fi driver architecture overview Design overview *************** -The nRF70 Series Wi-Fi driver follows an OS agnostic design, and the driver implementation is split into OS agnostic and OS (Zephyr) specific code. +The nRF Wi-Fi driver follows an OS agnostic design, and the driver implementation is split into OS agnostic and OS (Zephyr) specific code. The OS agnostic code is located in the :file:`drivers/wifi/nrf700x/osal/` folder and the OS specific code is located in the :file:`drivers/wifi/nrf700x/zephyr/` folder. -The driver supports two modes of operations: +The driver supports two modes of operation: Wi-Fi mode ========== @@ -43,21 +43,19 @@ It is implemented as a network interface driver. The driver supports the following IEEE 802.11 features: * Wi-Fi 6 (802.11ax) support -* WPA3/WPA2 personal security +* WPA3™/WPA2™ personal security * IEEE 802.11 Power Save modes -* Scan only mode -* IEEE 802.11 Station (STA) mode +* Scan-only mode +* IEEE 802.11 :term:`Station mode (STA)` +* :term:`Software-enabled Access Point (SoftAP or SAP)` mode -The following features are in the driver code but not yet supported: +The Wi-Fi Direct® mode feature is in the driver code but is not yet supported. -* IEEE 802.11 AP mode (Soft AP) -* Wi-Fi Direct mode - -Except for scan only mode, the driver uses host access point daemon (hostapd) to implement AP Media Access Control (MAC) Sublayer Management Entity (AP MLME) and wpa_supplicant to implement 802.1X supplicant. +Except for scan-only mode, the driver uses the host access point daemon (hostapd) to implement AP Media Access Control (MAC) Sublayer Management Entity (AP MLME) and wpa_supplicant to implement 802.1X supplicant. Radio Test mode =============== -The nRF70 Series Wi-Fi driver supports Radio Test mode, which you can use to test the RF performance of the nRF70 Series device. +The nRF Wi-Fi driver supports Radio Test mode, which you can use to test the RF performance of the nRF70 Series device. This is a build time option that you can enable using the :kconfig:option:`CONFIG_NRF700X_RADIO_TEST` Kconfig option. For more details about using this driver in Radio Test mode, see :ref:`wifi_radio_test`. @@ -66,15 +64,15 @@ Driver to nRF70 Series device communication ******************************************* The driver communicates with the nRF70 Series device using the QSPI/SPI interface. -The driver uses the QSPI/SPI interface to send commands to the nRF70 Series device, and to transfer the data to and from the device. -The nRF7002 DK uses QSPI whereas the nRF7002 EK uses SPI. +The driver uses the QSPI/SPI interface to send commands to the nRF70 Series device, and to transfer data to and from the device. +The nRF7002 DK uses QSPI, whereas the nRF7002 EK uses SPI. To connect the nRF7002 EK to the SoC, the ``nrf7002ek`` shield is required. Configuration ************* -The nRF70 Series Wi-Fi driver has the following configuration options: +The nRF Wi-Fi driver has the following configuration options: Kconfig configuration ===================== @@ -150,7 +148,7 @@ The following table lists the parameters (8-bit unsigned values) defined in the API documentation ***************** -After the nRF70 Series driver has been initialized, the application will see it as an Ethernet interface. +After the nRF Wi-Fi driver has been initialized, the application will see it as an Ethernet interface. To use the Ethernet interface, the application can use `Zephyr Network APIs`_. See the :ref:`nrfxlib:nrf_wifi_api` to learn more about various modes of low-level API. diff --git a/doc/nrf/external_comp/avsystem.rst b/doc/nrf/external_comp/avsystem.rst index 006c45a71d3..aa65dd9513d 100644 --- a/doc/nrf/external_comp/avsystem.rst +++ b/doc/nrf/external_comp/avsystem.rst @@ -176,7 +176,7 @@ Applications and samples The following application uses the AVSystem integration in |NCS|: -* :ref:`asset_tracker_v2` - The :ref:`asset_tracker_v2_cloud_module` is set to communicate with AVSystem's Coiote Device Management, with a runtime provisioned Pre-shared key (PSK) set by the ``CONFIG_LWM2M_INTEGRATION_PSK`` Kconfig option. +* :ref:`asset_tracker_v2` - The :ref:`asset_tracker_v2_cloud_module` is set to communicate with AVSystem's Coiote Device Management, with a runtime provisioned pre-shared key (PSK) set by the ``CONFIG_LWM2M_INTEGRATION_PSK`` Kconfig option. For more information, see :ref:`assettracker_v2_cloudmodule_lwm2m`. The following samples use the AVSystem integration in |NCS|: @@ -185,7 +185,7 @@ The following samples use the AVSystem integration in |NCS|: * :ref:`lwm2m_carrier` * :ref:`modem_shell_application` -All these samples offer LwM2M support and can be used to fetch location assistance data from nRF Cloud by proxying it through AVSystem's Coiote LwM2M server. +All these samples offer LwM2M support and can be used to fetch location assistance data from nRF Cloud by proxying it through AVSystem's Coiote LwM2M Server. Library support *************** diff --git a/doc/nrf/external_comp/bt_fast_pair.rst b/doc/nrf/external_comp/bt_fast_pair.rst index 4ca4ac896d5..2b24e75f8a8 100644 --- a/doc/nrf/external_comp/bt_fast_pair.rst +++ b/doc/nrf/external_comp/bt_fast_pair.rst @@ -1,13 +1,13 @@ .. _ug_bt_fast_pair: -Using Google Fast Pair with the |NCS| -##################################### +Google Fast Pair integration +############################ .. contents:: :local: :depth: 2 -Google Fast Pair is a standard for pairing Bluetooth® and Bluetooth Low Energy (LE) devices with as little user interaction required as possible. +Google Fast Pair is a standard for pairing *Bluetooth®* and Bluetooth Low Energy (LE) devices with as little user interaction required as possible. Google also provides additional features built upon the Fast Pair standard. For detailed information about supported functionalities, see the official `Fast Pair`_ documentation. @@ -18,6 +18,27 @@ For detailed information about supported functionalities, see the official `Fast The implementation passes tests of `Fast Pair Validator app`_ (beta version). The procedure triggered in Android settings is successful (tested with Android 11). +Integration prerequisites +************************* + +Before you start the |NCS| integration with Fast Pair, make sure that the following prerequisites are fulfilled: + +* :ref:`Install the nRF Connect SDK `. +* Set up a supported :term:`Development Kit (DK)`. + See :ref:`device_guides` for more information on setting up the DK you are using. +* Install the requirements mentioned in the :ref:`bt_fast_pair_provision_script`. + The script is automatically invoked by the build system during application build to generate Fast Pair provisioning data hex file. +* During the early stages of development, you can use the debug Model ID and Anti-Spoofing Public/Private Key pair obtained by Nordic Semiconductor for local tests. + Later on, you need to register your own Fast Pair Provider device with Google. + The :ref:`ug_bt_fast_pair_provisioning_register` section in this document explains how to register the device and obtain the Model ID and Anti-Spoofing Public/Private Key pair. + +Solution architecture +********************* + +The |NCS| integrates the Fast Pair Provider role, facilitating communication between the Fast Pair Seeker (typically a smartphone) and the Provider (your device). +The integration involves following the instructions outlined in the :ref:`ug_integrating_fast_pair` section. +The SDK supports extensions such as Battery Notification and Personalized Name, which can be included based on the specific use case requirements. + .. _ug_fast_pair_extensions: Google Fast Pair extensions @@ -51,8 +72,8 @@ For more details on this extension, see the `Fast Pair Personalized Name extensi .. _ug_integrating_fast_pair: -Integrating Fast Pair -********************* +Integration steps +***************** The Fast Pair standard integration in the |NCS| consists of the following steps: @@ -87,8 +108,8 @@ See the official `Fast Pair Model Registration`_ documentation for information o Alternatively, you can use the debug Model ID and Anti-Spoofing Public/Private Key pair obtained by Nordic Semiconductor for the development purposes. See the following samples and applications for details about the debug Fast Pair Providers registered by Nordic: -* the :ref:`fast_pair_input_device` sample -* the :ref:`nrf_desktop` application +* The :ref:`fast_pair_input_device` sample +* The :ref:`nrf_desktop` application .. _ug_bt_fast_pair_provisioning_register_device_type: @@ -136,21 +157,27 @@ You must enable the :kconfig:option:`CONFIG_BT_FAST_PAIR` Kconfig option to supp An application can communicate with the Fast Pair subsystem using API calls and registered callbacks. The Fast Pair subsystem uses the registered callbacks to inform the application about the Fast Pair related events. -The application must register the callbacks before it starts to operate as the Fast Pair Provider and advertise Bluetooth LE packets. +The application must register the callbacks before it enables the Fast Pair subsystem and starts to operate as the Fast Pair Provider and advertise Bluetooth LE packets. To identify the callback registration functions in the Fast Pair API, look for the ``_register`` suffix. Set your application-specific callback functions in the callback structure that is the input parameter for the ``..._register`` API function. The callback structure must persist in the application memory (static declaration), as during the registration, the Fast Pair module stores only the memory pointer to it. -The standard Fast Pair API (without extensions) currently supports the :c:func:`bt_fast_pair_info_cb` function (optional) for registering application callbacks. +The standard Fast Pair API (without extensions) currently supports the :c:func:`bt_fast_pair_info_cb_register` function (optional) for registering application callbacks. The standard Fast Pair (without extensions) does not require registration of any callback type, meaning all callbacks are optional. -Apart from the callback registration, no additional operations are needed to integrate the standard Fast Pair implementation. +After the callback registration, the Fast Pair subsystem must be enabled with the :c:func:`bt_fast_pair_enable` function. +Before performing the :c:func:`bt_fast_pair_enable` operation, you must enable Bluetooth with the :c:func:`bt_enable` function and load Zephyr's :ref:`zephyr:settings_api` with the :c:func:`settings_load` function. +The Fast Pair subsystem readiness can be checked with the :c:func:`bt_fast_pair_is_ready` function. +The Fast Pair subsystem can be disabled with the :c:func:`bt_fast_pair_disable` function. +In the Fast Pair subsystem disabled state, most of the Fast Pair APIs are not available. + +Apart from the callback registration and enabling the Fast Pair subsystem, no additional operations are needed to integrate the standard Fast Pair implementation. Personalized Name extension =========================== -To support the Personalized Name extension, ensure that the :kconfig:option:`CONFIG_BT_FAST_PAIR_EXT_PN` Kconfig option is enabled in your project. +To support the Personalized Name extension, ensure that the :kconfig:option:`CONFIG_BT_FAST_PAIR_PN` Kconfig option is enabled in your project. This extension is enabled by default. .. rst-class:: numbered-step @@ -242,6 +269,9 @@ The service implements functionalities required by the `Fast Pair Procedure`_. The procedure is initiated by the Fast Pair Seeker after Bluetooth LE connection is established. No application interaction is required. +The Fast Pair GATT service is statically defined, so it is still present in the GATT database after the Fast Pair subsystem is disabled. +In the Fast Pair subsystem disabled state, GATT operations on the Fast Pair service are rejected. + The Fast Pair GATT service modifies default values of related Kconfig options to follow Fast Pair requirements. The service also enables the needed functionalities using Kconfig select statement. For details, see the :ref:`bt_fast_pair_readme` Bluetooth service documentation in the |NCS|. @@ -269,6 +299,9 @@ Managing factory resets The Fast Pair GATT service uses a non-volatile memory to store the Fast Pair user data such as Account Keys and the Personalized Name. This data can be cleared by calling the :c:func:`bt_fast_pair_factory_reset` function. +Calling the :c:func:`bt_fast_pair_factory_reset` function does not affect the Fast Pair subsystem's readiness. +If the subsystem is enabled with the :c:func:`bt_fast_pair_enable` function, it stays enabled after calling the :c:func:`bt_fast_pair_factory_reset` function. +The same applies for the Fast Pair subsystem disabled state. For details, see the :c:func:`bt_fast_pair_factory_reset` function documentation. .. _ug_bt_fast_pair_factory_reset_custom_user_reset_action: @@ -282,8 +315,8 @@ Optionally, you can also define the :c:func:`bt_fast_pair_factory_reset_user_act Both functions are defined as weak no-op functions. Ensure that your reset action implementation executes correctly in the following execution contexts: -* In the :c:func:`bt_fast_pair_factory_reset` function context: the factory reset action is triggered by calling the :c:func:`bt_fast_pair_factory_reset` function. -* In the :c:func:`settings_load` function context during the commit phase (after data is loaded from the non-volatile memory): the factory reset action using the :c:func:`bt_fast_pair_factory_reset` function was interrupted and the factory reset is retried on the system bootup. +* In the :c:func:`bt_fast_pair_factory_reset` function context - The factory reset action is triggered by calling the :c:func:`bt_fast_pair_factory_reset` function. +* In the :c:func:`bt_fast_pair_enable` function context - The factory reset action using the :c:func:`bt_fast_pair_factory_reset` function was interrupted, and the factory reset is retried when enabling the Fast Pair subsystem. .. caution:: If the factory reset operation constantly fails due to an error in the custom user reset action, the system may never be able to properly boot-up. @@ -302,3 +335,42 @@ The specific use case of the Google Fast Pair application is indicated by the ch Different use cases may require implementation of additional guidelines for your accessory firmware or specific configuration of your device model in the Google Nearby Devices console. These requirements typically help to improve user experience or security properties for the chosen use case. To learn more, see the official `Fast Pair`_ documentation. + +Applications and samples +************************ + +The following application and sample use the Fast Pair integration in the |NCS|: + +* :ref:`nrf_desktop` application +* :ref:`fast_pair_input_device` sample + +Library support +*************** + +The following |NCS| libraries support the Fast Pair integration: + +* :ref:`bt_fast_pair_readme` library implements the Fast Pair GATT Service and provides the APIs required for :ref:`ug_bt_fast_pair` with the |NCS|. +* :ref:`bt_le_adv_prov_readme` library - Google Fast Pair advertising data provider (:kconfig:option:`CONFIG_BT_ADV_PROV_FAST_PAIR`) can be used to integrate Fast Pair advertising payload to this library. + The Bluetooth LE advertising provider subsystem can be used to manage advertising and scan response data. + +Required scripts +**************** + +The :ref:`bt_fast_pair_provision_script` is required to generate the provisioning data for the device. +The script is automatically invoked by the build system during application build when the :kconfig:option:`CONFIG_BT_FAST_PAIR` Kconfig option is enabled. + +Terms and licensing +******************* + +The use of Google Fast Pair may be subject to Google's terms and licensing. +Refer to the official `Fast Pair`_ documentation for development-related licensing information. + +Dependencies +************ + +The following are the required dependencies for the Fast Pair integration: + +* :ref:`nrfxlib:crypto` +* :ref:`zephyr:bluetooth` +* :ref:`zephyr:settings_api` +* :ref:`partition_manager` diff --git a/doc/nrf/external_comp/coremark.rst b/doc/nrf/external_comp/coremark.rst new file mode 100644 index 00000000000..fe16eefdf13 --- /dev/null +++ b/doc/nrf/external_comp/coremark.rst @@ -0,0 +1,92 @@ +.. _ug_coremark: + +CoreMark integration +#################### + +.. contents:: + :local: + :depth: 2 + +CoreMark® is a CPU benchmark provided by Embedded Microprocessor Benchmark Consortium (EEMBC) to verify SoCs performance. +You can use it to perform series of tests in each benchmark iteration. +The benchmark score is calculated based on the number of iterations per second the :term:`Device Under Test (DUT)` can perform. +Integrating CoreMark into the |NCS| allows users to easily verify SoCs performance. + +Integration prerequisites +************************* + +Before you start the |NCS| integration with CoreMark, make sure that the following prerequisites are completed: + +* :ref:`Installation of the nRF Connect SDK `. +* Setup of the supported :term:`Development Kit (DK)`. + +Solution architecture +********************* + +Adding the CoreMark repository to the |NCS| manifest automatically includes it in the repository as the |NCS| module. +You can find it under the :file:`modules/benchmark/coremark` path. +CoreMark needs a porting layer to run correctly on a SoC. +You can find the files of porting layer for devices supported in the |NCS| under the :file:`nrf/modules/coremark` path. + +CoreMark benchmark consists of continuously repeated iterations. +Each iteration, in turn, consists of the following workloads: + +* Linked list +* Matrix multiply +* State machine + +For detailed description of each of those workloads, see the `CoreMark GitHub`_ repository. + +Integration steps +***************** + +To integrate CoreMark into the |NCS|, configure CoreMark as described in the following section. + +Configuring CoreMark +==================== + +To include CoreMark in your build, complete the following steps: + +#. Add the following Kconfig options in your :file:`prj.conf` file: + + .. code-block:: console + + CONFIG_COREMARK=y + +#. Choose any of the following memory methods for dealing with the CoreMark data. + Make sure that you allocate enough memory, depending on the method you choose. + + * Memory method stack: + + .. code-block:: console + + COREMARK_MEMORY_METHOD_STACK=y + CONFIG_MAIN_STACK_SIZE=4096 + + * Memory method heap: + + .. code-block:: console + + CONFIG_COREMARK_MEMORY_METHOD_MALLOC=y + CONFIG_HEAP_MEM_POOL_SIZE=4096 + + * Memory method static: + + .. code-block:: console + + CONFIG_COREMARK_MEMORY_METHOD_STATIC=y + +To see an example, refer to the :ref:`coremark_configuration` section of the :ref:`coremark_sample` documentation. + +Submitting score +**************** + +You can see the submitted scores in the official `CoreMark `_ database. +If you want to submit your own score, follow steps in the `CoreMark GitHub`_ repository. + +Applications and samples +************************ + +The following sample demonstrates the CoreMark integration in the |NCS|: + +* :ref:`coremark_sample` - This sample is used to obtain the CoreMark score for boards supported in the |NCS|. diff --git a/doc/nrf/external_comp/memfault.rst b/doc/nrf/external_comp/memfault.rst index 78bd712658b..01862a62759 100644 --- a/doc/nrf/external_comp/memfault.rst +++ b/doc/nrf/external_comp/memfault.rst @@ -93,7 +93,7 @@ See the following example on how to set an overlay configuration for Memfault in .. code-block:: console - west build -b nrf9160dk_nrf9160_ns -- -DOVERLAY_CONFIG=overlay-memfault.conf + west build -b nrf9160dk_nrf9160_ns -- -DEXTRA_CONF_FILE=overlay-memfault.conf .. rst-class:: numbered-step diff --git a/doc/nrf/external_comp/nrf_cloud.rst b/doc/nrf/external_comp/nrf_cloud.rst index 1acc86f2ffb..0ae85e37eca 100644 --- a/doc/nrf/external_comp/nrf_cloud.rst +++ b/doc/nrf/external_comp/nrf_cloud.rst @@ -119,11 +119,11 @@ A device can successfully connect to `nRF Cloud`_ using MQTT if the following re * It creates a device certificate and signs it with the specified CA. * It writes the device certificate and AWS CA certificate to the device. - #. Run the `nrf_cloud_provision.py`_ script to provision and associate the device with your nRF Cloud account. + #. Run the `nrf_cloud_onboard.py`_ script to onboard the device to your nRF Cloud account. For more details about the scripts, refer to the `nRF Cloud Utilities documentation`_. - See `Securely generating credentials`_ and `nRF Cloud Provisioning`_ for more details. + See `Securely generating credentials`_ and `nRF Cloud Provisioning`_ for more details. |NCS| library support diff --git a/doc/nrf/glossary.rst b/doc/nrf/glossary.rst index d44105ebb7a..151bc824e1f 100644 --- a/doc/nrf/glossary.rst +++ b/doc/nrf/glossary.rst @@ -15,6 +15,9 @@ Glossary In the |NCS|, it uses ``APPROTECT`` registers and several Kconfig options, as described in :ref:`app_approtect`. See also :term:`Secure access port protection mechanism (Secure AP-Protect)`. + Advanced eXtensible Interface (AXI) Communication + A system that transfers data between components inside a computer or between computers. + AHB Access Port (AHB-AP) An Arm Coresight component that allows a debug probe to access CPU cores for programming and debugging. Access through the AHB-AP can be blocked with :term:`Access port protection mechanism (AP-Protect)`. @@ -59,6 +62,13 @@ Glossary Basic Service Set Identifier (BSSID) The MAC address of an access point. + BELLBOARD + A peripheral associated with a given core that provides support for the inter-domain SW signaling. + It includes a set of tasks and events intended for signaling within an interprocessor communication (IPC) framework. + + Bill of materials (BoM) + List of the raw materials, sub-assemblies, intermediate assemblies, sub-components, parts, and the quantities of each needed to manufacture an end product. + Binary Convolutional Codes (BCC) A type of error-correcting code that generates parity symbols using the sliding application of a boolean polynomial function to a data stream. @@ -93,8 +103,11 @@ Glossary Build type A build type is a feature that defines the way in which the configuration files are to be handled. - The |NCS| provides support for :ref:`app_build_additions_build_types`. - Selecting a specific build type can result in a different structure of the :term:`build configuration`. + The |NCS| provides support for handling :ref:`app_build_additions_build_types` + :ref:`Selecting a specific build type ` can result in a different structure of the :term:`build configuration`. + + .. note:: + Build types are deprecated and are being gradually replaced by Zephyr's :ref:`file suffixes ` and :ref:`zephyr:sysbuild`. Carrier-sense Multiple Access with Collision Avoidance (CSMA/CA) A network multiple access method in which carrier sensing is used, but nodes attempt to avoid collisions by beginning transmission only after the channel is sensed to be idle. @@ -145,6 +158,10 @@ Glossary Contribution A change to the codebase sent to a remote :term:`repository ` for inclusion. + Core + Subsets of :term:`domains `. + Most memory and peripherals can be flexibly allocated to cores at compile time. + Cortex Microcontroller Software Interface Standard (CMSIS) A vendor-independent hardware abstraction layer for the Cortex-M processor series that defines generic tool interfaces. @@ -152,6 +169,9 @@ Glossary A group term for different security extensions for the Arm Cortex-M33 processor. In the |NCS|, this term is used in the context of `ARM TrustZone`_ and :ref:`app_boards_spe_nspe` (:term:`Non-Secure Processing Environment (NSPE)` and :term:`Secure Processing Environment (SPE)`). + CRACEN + A hardware cryptographic engine within nRF54H devices. + Data Terminal Ready (DTR) A control signal in RS-232 serial communications transmitted from data terminal equipment, such as a computer, to data communication equipment. @@ -175,6 +195,9 @@ Glossary Device Under Test (DUT) A manufactured product undergoing testing. + Dynamic Voltage and Frequency Scaling (DVFS) + A power management technique that allows adjusting the operating voltage and operating frequency of a CPU, depending on the workload. + Docker A set of software tools using OS-level virtualization to create and run applications and their dependencies in self-contained environments called :term:`Docker containers `. @@ -188,22 +211,37 @@ Glossary Docker engine The :term:`Docker container` runtime that runs :term:`Docker images `. + Domain + Functional blocks included in the system/SoC. + Contains the user-programmable main CPU and its associated functions. + Domain Name System (DNS) A hierarchical distributed naming system for computers, services, or any resource connected to the Internet or a private network. It associates various information with domain names assigned to each of the participating entities. Most prominently, it translates domain names, which can be easily memorized by humans, to the numerical IP addresses needed for computer services and devices worldwide. The Domain Name System is an essential component of the functionality of most Internet services because it is the Internet's primary directory service. + Downlink (DL) + A signal coming from the :term:`Evolved Node B (eNB)` to the :term:`User equipment (UE)`. + Downstream fork A :term:`repository ` located downstream, relative to another repository, in the flow of information. See :ref:`dm_repo_types`. + Easy Direct Memory Access (EasyDMA) + A module that some peripherals implement to gain direct access to data RAM. + Embedded Universal Integrated Circuit Card (eUICC) A component of a SIM card that enables switching Mobile Network Operators over-the-air. Endpoint In the context of a :ref:`Matter ` or :ref:`Zigbee ` network, an addressable container that contains *clusters* appropriate for a single device type such as a sensor or a light bulb. + Enhanced ShockBurst (ESB) + A basic protocol supporting two-way data packet communication including packet buffering, packet acknowledgment, and automatic retransmission of lost packets. + ESB provides radio communication with low power consumption. + The implementation is small in code size and easy to use. + Ephemeris data In the :term:`Global Navigation Satellite System (GNSS)`, the data providing information about the orbit of the satellite transmitting it. This data is valid for four hours and becomes inaccurate after that. @@ -223,6 +261,16 @@ Glossary Extended Discontinuous Reception (eDRX) A method to conserve the battery of an Internet of Things (IoT) device by allowing it to remain inactive for extended periods. + External Memory Interface (EXMIF) + A bus protocol for communication from an integrated circuit, such as a microprocessor, to an external memory device located on a circuit board. + + External Memory Interface Encryption Engine (EXMEE) + A peripheral that supports on-the-fly encryption and authentication for the memory connected to EXMIF. + The AES tweaked mode is used to provide encryption, and one of single hash, granular hash, or Merkle tree is used to provide authentication, using the SHA3 algorithm. + + Fast Lightweight Processor (FLPR, pronounced “Flipper”) + A processor that is located in the high-speed portion of the Global Domain primarily intended to implement software-defined peripheral functions. + Firmware Over-the-Air (FOTA) update A firmware update performed remotely over-the-air (OTA). @@ -236,6 +284,15 @@ Glossary Forward Error Correction (FEC) A technique that adds redundant data to the original message, which is used to detect and correct errors that occur during transmission over a network improving the overall performance by reducing the number of errors and retransmissions. + Frequency Division Duplex (FDD) + A method used in wireless communication that uses different frequencies for uplink and downlink, which allows the user to transmit and receive simultaneously. + + Frequency-locked loop (FLL) + An electronic control system that generates a signal that is locked to the frequency of an input or "reference" signal. + + Fully Depleted Silicon-on-Insulator (FD-SOI) + A type of SOI technology that uses a thin layer of silicon that is fully depleted of electrons. + GitHub fork A `GitHub fork`_ is a copy of a repository inside GitHub, that allows the user to create a :term:`Pull Request`. @@ -269,6 +326,7 @@ Glossary Hardware Flow Control (HWFC) A handshaking mechanism used to prevent an overflow of bytes in modems. It uses two dedicated pins on the RS-232 connector, :term:`Request to Send (RTS)` and :term:`Clear to Send (CTS)`. + The :ref:`default serial port connection settings ` in the |NCS| use HWFC set to ``None``. Host Controller Interface (HCI) Standardized communication between the host stack (for example, a PC or mobile phone OS) and the controller (the Bluetooth IC). @@ -312,6 +370,9 @@ Glossary The latest version of the Internet Protocol (IP). It is the communications protocol that provides an identification and location system for computers on networks and routes traffic across the Internet. + Interprocessor Communication Transceiver (IPCT) + A peripheral used for direct signalling between peripherals in other domains. + IPv4 address A numerical label that is used to identify a network interface of a computer or other network node participating in an IPv4 computer network. @@ -408,13 +469,22 @@ Glossary MCUboot A secure bootloader for 32-bit microcontroller units, which is independent of hardware and operating system. - Mcumgr + MCUmgr A management library for 32-bit MCUs. It uses the :term:`Simple Management Protocol (SMP)`. Media Access Control address (MAC address) The unique 48-bit serial number in the network circuitry of every Ethernet and Wi-Fi device. + Memory Privilege Controller (MPC) + Performs security configuration, enforcement, and bus decoding. + It implements security filtering, checking bus accesses against the configured access properties and blocking any unauthorized accesses. + + Memory-to-memory Vector Direct Memory Access (MVDMA) + A peripheral capable of copying data from one memory address to another memory address. + It is not a complement to the EasyDMA (:term:`Easy Direct Memory Access (EasyDMA)`). + The scatter-gather property applies to MVDMA as well. + Memory Watch Unit (MWU) A peripheral that can be used to generate events when a memory region is accessed by the CPU. @@ -435,6 +505,9 @@ Glossary Modulation Coding Scheme (MCS) An index defined by the Wi-Fi standards where each index specifies a combination of modulation scheme and forward error correction coding rate. + Monitor + A network interface mode for nRF70 Series devices that enables the capture and analysis of all incoming IEEE 802.11 packets. + Multicast addressing An addressing type that uses a one-to-many association, where datagrams are routed from a single sender to multiple selected endpoints simultaneously in a single transmission. @@ -540,15 +613,35 @@ Glossary It does not require a repository. Sometimes it is improperly used as a synonym of :term:`commit `. + Peripheral CPU Device Firmware Update (PCD) + A library that adds functionality for transferring DFU images from the application core to the network core on the nRF5340 SoC. + + Peripheral Processor (PPR, pronounced “Pepper”) + A processor that is located in the low-leakage portion of the Global Domain and is primarily intended to: + + * Handle peripherals in low-power states while the main processors are in sleep mode. + * Coordinate peripherals. + * Implement low-level protocols for communicating with sensors and actuators + Personal Unblocking Key (PUK) A key used to reset a PIN that has been lost or forgotten for a SIM card. + Physically Unclonable Function (PUF) + A function device that exploits inherent randomness introduced during manufacturing to give a physical entity a unique "fingerprint" or a trust anchor. + + Platform Security Architecture Certified (PSA Certified) + A security certification scheme for Internet of Things (IoT) hardware, software and devices. + Power Amplifier (PA) A device used to increase the transmit power level of a radio signal. Power Management Integrated Circuit (PMIC) A chip used for various functions related to power management. + Power Management Service + A service that automatically handles the settings described by an application. + It decides how registers will be retained, which parts of the device are put into what mode, and what clock signals are running. + Power Saving Mode (PSM) A feature introduced in 3GPP Release 12 to improve the battery life of IoT (Internet of Things) devices by minimizing energy consumption. The device stays dormant during the PSM window. @@ -585,6 +678,9 @@ Glossary Pull Request A set of :term:`commits ` that are sent as a :term:`contribution ` to a Git :term:`repository `. + Quad Serial Peripheral Interface (QSPI) + A peripheral that provides support for communicating with an external flash memory device using SPI. + Qualified Design Identification (QDID) A unique identifier assigned to a design that has completed the Bluetooth Qualification Process. @@ -656,6 +752,19 @@ Glossary In the |NCS|, it uses ``SECUREAPPROTECT`` registers and several Kconfig options, as described in :ref:`app_approtect`. See also :term:`Access port protection mechanism (AP-Protect)`. + Secure domain (SecDom) + A dedicated :term:`Domain` which executes a pre-compiled firmware component that is signed by Nordic Semiconductor. + It exposes security services to the other domains through an Interprocess Communication interface. + + Serial Peripheral Interface (SPI) + An interface bus commonly used to send data between microcontrollers and small peripherals such as shift registers, sensors, and SD cards. + + Serial Peripheral Interface Master (SPIM) + A peripheral that can communicate with multiple slaves using individual chip select signals for each of the slave devices attached to a bus. + + Serial Peripheral Interface Slave (SPIS) + A peripheral used for ultra-low power serial communication from an external SPI master. + Secure Processing Environment (SPE) One of the two processing environments when using Cortex-M Security Extensions. When firmware is separated between :term:`Non-Secure Processing Environment (NSPE)` and SPE, SPE is used to store security features. @@ -676,11 +785,14 @@ Glossary The level of signal power compared to the level of noise power, often expressed in decibels (dB). Simple Management Protocol (SMP) - A transport protocol used by :term:`Mcumgr`. + A transport protocol used by :term:`MCUmgr`. Simple Network Time Protocol (SNTP) A less complex implementation of :term:`Network Time Protocol (NTP)`, using the same protocol but without requiring the storage of state over extended periods of time. + Software-enabled Access Point (SoftAP or SAP) + A network device operating as an IEEE 802.11 access point using software with limited functionality. + Soft fork A :term:`fork ` that contains a very small set of changes when compared to its upstream. @@ -691,6 +803,10 @@ Glossary Software Development Kit (SDK) A set of tools used for developing applications for a specific device or operating system. + Spin-Transfer Torque Magneto-Resistive Random Access Memory (MRAM (STT-MRAM)) + An alternative :term:`Non-volatile memory (NVM)` to flash memory. + Compared to flash, MRAM does not have to be erased before writing and can simply be written, making it easier to use. + Spinel A general management protocol for enabling a host device to communicate with and manage co-processors, like a network co-processor (NCP) or a radio co-processor (RCP). @@ -704,6 +820,9 @@ Glossary Supervisor Call (SVC) It generates a software exception in which access to system resources or privileged operations can be provided. + System Controller + A :term:`VPR Core` that implements system startup and power management functionalities that in the past would have been implemented in hardware. + System in Package (SiP) Several integrated circuits, often from different technologies, enclosed in a single module that performs as a system or subsystem. @@ -721,12 +840,28 @@ Glossary A function that allows an access point to define a specific time or set of times for individual devices to access the wireless network. It is the mechanism that allows devices to negotiate when and how often they turn on and off, based on when they need to send and receive data. + Tightly Coupled Memory (TCM) + Part of RAM which provides a low-latency memory access that the core can use with predictable access time. + Unlike cached memories for which the access latency is unpredictable. + Temporal Key Integrity Protocol (TKIP) A security protocol used in the IEEE 802.11 wireless networking standard. + Time Division Duplex (TDD) + A method used in wireless communication that uses same frequencies for uplink and downlink, but in a different timeslots. + Time to First Fix (TTFF) The time needed by a :term:`Global Navigation Satellite System (GNSS)` module to estimate its position. + TIMER + A peripheral that runs on the high-frequency clock source (HFCLK) and includes a four-bit (1/2X) prescaler that can divide the timer input clock from the HFCLK controller. + It can operate in two modes: timer and counter. + + Toolchain + A set of development tools: compiler, assembler, and linker. + The Zephyr SDK includes this set plus a couple more Zephyr-specific tools. + The |NCS| toolchain is based on the Zephyr SDK and then adds on top of it a :ref:`set of tools and modules specific to the nRF Connect SDK ` that are required to build |NCS| samples and applications. + Traffic Indication Map (TIM) A field in the Wi-Fi access point's beacon frame containing information about which Wi-Fi stations have buffered data waiting for them. This allows devices in power save mode to remain in a low-power state until they have data waiting for them. @@ -735,17 +870,19 @@ Glossary A connection-oriented protocol that provides reliable transport. This reliability comes at the cost of control packets overhead of the protocol itself, making it unsuitable for bandwidth-constrained applications. - Toolchain - A set of development tools: compiler, assembler, and linker. - The Zephyr SDK includes this set plus a couple more Zephyr-specific tools. - The |NCS| toolchain is based on the Zephyr SDK and then adds on top of it a :ref:`set of tools and modules specific to the nRF Connect SDK ` that are required to build |NCS| samples and applications. - Transmit Data (TXD) A signal line in a serial interface that transmits data to another device. + Trusted Third Party (TTP) + An entity which facilitates interactions between two parties who both trust the third party. + + TrustZone + Provides a cost-effective methodology to isolate security-critical components in an ARM Cortex CPU by hardware separating a rich operating system from smaller, secure operating system. + UART Hardware Flow Control (UART HWFC) A handshaking mechanism used to prevent a buffer overflow in the receiver (in embedded computing use cases). In a serial connection, when the transmission baud rate is high enough for data to appear faster than it can be processed by the receiver, the communicating devices can synchronize with each other, using :term:`Request to Send (RTS)` and :term:`Clear to Send (CTS)` pins. + In the |NCS|, UART HWFC is usually not used when :ref:`testing applications `. Unicast addressing An addressing type that uses a one-to-one association between the destination address and the network endpoint. @@ -757,6 +894,9 @@ Glossary Universal Serial Bus (USB) An industry standard that establishes specifications for cables and connectors and protocols for connection, communication, and power supply between computers, peripheral devices, and other computers. + Uplink (UL) + A signal sent from the :term:`User equipment (UE)` to the :term:`Evolved Node B (eNB)`. + Upmerge In the |NCS|, the act of updating (synchronizing) a downstream :term:`repository ` with a newer revision of its :term:`upstream ` OSS repository. @@ -778,6 +918,18 @@ Glossary Version A string that identifies a project release. + VPR Core + Pronounced "Viper Core", a :term:`Core` that is compatible with the RISC-V instruction set, meaning the industry-standard RISC-V development tools can be used. + VPR implements the RV32E instruction set (Base Integer Instruction Set (embedded) - 32 bit, 16 registers) and the following extensions: + + * M: Multiply and divide extension + * C: Compressed extension (compressed instructions) + + The nRF54H20 DK uses several VPR cores: :term:`Fast Lightweight Processor (FLPR, pronounced “Flipper”)`, :term:`Peripheral Processor (PPR, pronounced “Pepper”)` and :term:`System Controller`. + + VPR Event Interface (VEVIF) + A real-time peripheral that allows interaction with the VPR's interrupts and the PPI system in the domain where the VPR is instantiated. + Watchdog timer (WDT) A timer that causes a system reset if it is not poked periodically. @@ -787,15 +939,15 @@ Glossary See :ref:`zephyr:west`. West manifest file - The main file describing the contents of a :term:`West` workspace, which is located in the :term:`West manifest repository`. + The main file describing the contents of a :term:`west ` workspace, which is located in the :term:`west manifest repository `. In the |NCS| and Zephyr, it is named :file:`west.yml`. West manifest repository - A :term:`repository ` that contains a :term:`West manifest file` and can be used to configure a west workspace. + A :term:`repository ` that contains a :term:`west manifest file ` and can be used to configure a west workspace. See :ref:`dm_repo_types`. West project - Any of the listed :term:`repositories ` inside a :term:`West manifest file`. + Any of the listed :term:`repositories ` inside a :term:`west manifest file `. Wi-Fi Protected Access® (WPA) A security protocol developed by Wi-Fi Alliance. diff --git a/doc/nrf/images/ncs-toolchain.svg b/doc/nrf/images/ncs-toolchain.svg index 4172f0fb383..e050e2e4835 100644 --- a/doc/nrf/images/ncs-toolchain.svg +++ b/doc/nrf/images/ncs-toolchain.svg @@ -2,20 +2,24 @@ + width="6.45132in" height="3.9739in" viewBox="0 0 464.495 286.121" xml:space="preserve" color-interpolation-filters="sRGB" + class="st14"> @@ -23,52 +27,130 @@ - + Page-1 - + Nordic Blueslate Kconfig - - Kconfig - + + Kconfig + Nordic Blueslate.2 Devicetree - - Devicetree - + + Devicetree + Dynamic connector - + - + Dynamic connector.1712 - + - + Nordic Blueslate.3 CMake - - CMake - + + CMake + Nordic Blueslate.4 Ninja - - Ninja - + + Ninja + Nordic Blueslate.5 - GCC - - GCC - + Compiler (GCC) + + Compiler (GCC) + Dynamic connector.1713 - + - + Dynamic connector.1723 - + + + + Nordic Blueslate.1729 + CMakeLists.txt + + CMakeLists.txt + + Nordic Blueslate.1730 + Partition Manager + + Partition Manager + + Dynamic connector.1733 + + + + Dynamic connector.1734 + + + + Sheet.1746 + + Sheet.1731 + + Rectangle + + + + Sheet.1726 + Configuration phase + + Configuration phase + + + Sheet.1732 + + Rectangle.1725 + + + + Sheet.1728 + Building phase + + Building phase + + + Rectangle + + + + Sheet.1737 + CMake build + + CMake build + + Rectangle.1740 + + + + Rectangle.1741 + + + + Rectangle.1742 + + + + Rectangle.1743 + + + + Rectangle.1744 + + + + Rectangle.1745 + + diff --git a/doc/nrf/images/nrf5340_audio_application_topologies.png b/doc/nrf/images/nrf5340_audio_application_topologies.png new file mode 100644 index 00000000000..fd24b97ef31 Binary files /dev/null and b/doc/nrf/images/nrf5340_audio_application_topologies.png differ diff --git a/doc/nrf/images/nrf5340_audio_broadcast_sink_I2S_structure.svg b/doc/nrf/images/nrf5340_audio_broadcast_sink_I2S_structure.svg new file mode 100644 index 00000000000..57a4b0b3984 --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_broadcast_sink_I2S_structure.svg @@ -0,0 +1,470 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Blue + + + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.13 + HW codec (CS47L63) + + HW codec (CS47L63) + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + Synchronization module (audio_datapath.c) + + Synchronization module (audio_datapath.c) + + Nordic Lake + audio_i2s.c + + audio_i2s.c + + Nordic Blue.25 + + + + Dynamic connector.26 + + + + Dynamic connector.29 + + + + Nordic Lake.30 + I2S (audio) + + I2S (audio) + + Nordic Sky + audio_sync_timer.c + + audio_sync_timer.c + + Nordic Blue.33 + + + + Sheet.264 + Network core + + Network core + + Sheet.265 + Application core + + Application core + + Nordic Middle Grey.42 + + + + Dynamic connector.44 + + + + Dynamic connector.45 + + + + Dynamic connector.46 + + + + Sheet.273 + bad_frame + + bad_frame + + Sheet.274 + sdu_ref + + sdu_ref + + Sheet.275 + bad_frame + + bad_frame + + Sheet.276 + sdu_ref + + sdu_ref + + Dynamic connector.72 + + + + Dynamic connector.73 + + + + Dynamic connector.74 + + + + Sheet.281 + cur_time + + cur_time + + Dynamic connector.77 + + + + Sheet.283 + frame_start_ts + + frame_start_ts + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.287 + HCI IPC + + HCI IPC + + Sheet.288 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Sheet.291 + + Nordic Blue.24 + + + + Sheet.293 + Peripheral modules + + Peripheral modules + + + Nordic Blue.103 + + + + Nordic Lake.104 + + + + Dynamic connector.105 + + + + Sheet.297 + Control data + + Control data + + Dynamic connector.107 + + + + Sheet.299 + Compressed audio + + Compressed audio + + Dynamic connector.109 + + + + Sheet.301 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.111 + + + + Sheet.303 + Block working on compressed audio + + Block working on compressed audio + + Sheet.304 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.114 + + + + Sheet.306 + HW layer element + + HW layer element + + Nordic Lake.115 + + + + Sheet.308 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.310 + Large main module + + Large main module + + Sheet.311 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Nordic Lake.123 + + + + Sheet.315 + Synchronization module + + Synchronization module + + Dynamic connector.126 + + + + Nordic Blue.128 + Bluetooth LE Host + + Bluetooth LE Host + + Dynamic connector.129 + + + + Dynamic connector.130 + + + + Dynamic connector.131 + + + + Nordic Blue.129 + + + + Sheet.322 + Bluetooth modules + + Bluetooth modules + + Nordic Light Grey.142 + broadcast_sink.c + + broadcast_sink.c + + Dynamic connector.48 + + + + Dynamic connector.47 + + + + Nordic Lake.43 + Bluetooth LE RX FIFO + + Bluetooth LE RX FIFO + + Sheet.333 + main.c + + main.c + + Sheet.334 + + Nordic Light Grey.335 + sw_codec_select.c + + sw_codec_select.c + + Nordic Lake.336 + Decoder + + Decoder + + + Dynamic connector.337 + + + + diff --git a/doc/nrf/images/nrf5340_audio_broadcast_source_I2S_structure.svg b/doc/nrf/images/nrf5340_audio_broadcast_source_I2S_structure.svg new file mode 100644 index 00000000000..33fc352afb0 --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_broadcast_source_I2S_structure.svg @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Dynamic connector.68 + + + + Nordic Middle Grey + audio_system.c + + audio_system.c + + Nordic Light Grey + sw_codec_select.c + + sw_codec_select.c + + Nordic Blue + + + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.13 + HW codec (CS47L63) + + HW codec (CS47L63) + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + Synchronization module (audio_datapath.c) + + Synchronization module (audio_datapath.c) + + Nordic Lake + audio_i2s.c + + audio_i2s.c + + Nordic Blue.25 + ` + + ` + + Dynamic connector.26 + + + + Dynamic connector.29 + + + + Nordic Lake.30 + I2S (audio) + + I2S (audio) + + Nordic Lake.31 + I2S RX FIFO + + I2S RX FIFO + + Nordic Sky + audio_sync_timer.c + + audio_sync_timer.c + + Nordic Blue.33 + + + + Sheet.264 + Network core + + Network core + + Sheet.265 + Application core + + Application core + + Nordic Lake.37 + Encoder + + Encoder + + Dynamic connector.44 + + + + Dynamic connector.49 + + + + Dynamic connector.50 + + + + Dynamic connector.74 + + + + Dynamic connector.75 + + + + Sheet.281 + cur_time + + cur_time + + Dynamic connector.77 + + + + Sheet.283 + frame_start_ts + + frame_start_ts + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.287 + HCI IPC + + HCI IPC + + Sheet.288 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Sheet.291 + + Nordic Blue.24 + + + + Sheet.293 + Peripheral modules + + Peripheral modules + + + Nordic Blue.103 + + + + Nordic Lake.104 + + + + Dynamic connector.105 + + + + Sheet.297 + Control data + + Control data + + Dynamic connector.107 + + + + Sheet.299 + Compressed audio + + Compressed audio + + Dynamic connector.109 + + + + Sheet.301 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.111 + + + + Sheet.303 + Block working on compressed audio + + Block working on compressed audio + + Sheet.304 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.114 + + + + Sheet.306 + HW layer element + + HW layer element + + Nordic Lake.115 + + + + Sheet.308 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.310 + Large main module + + Large main module + + Sheet.311 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Nordic Lake.123 + + + + Sheet.315 + Synchronization module + + Synchronization module + + Dynamic connector.126 + + + + Nordic Blue.128 + Bluetooth LE Host + + Bluetooth LE Host + + Nordic Blue.129 + + + + Sheet.322 + Bluetooth modules + + Bluetooth modules + + Nordic Light Grey.139 + broadcast_source.c + + broadcast_source.c + + Dynamic connector.143 + + + + Nordic Sky.328 + main.c + + main.c + + diff --git a/doc/nrf/images/nrf5340_audio_broadcast_source_USB_structure.svg b/doc/nrf/images/nrf5340_audio_broadcast_source_USB_structure.svg new file mode 100644 index 00000000000..f4019ae99b7 --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_broadcast_source_USB_structure.svg @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Blue + Bluetooth LE Host + + Bluetooth LE Host + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + audio_system.c + + audio_system.c + + Nordic Lake + audio_usb.c + + audio_usb.c + + Nordic Blue.25 + + + + Dynamic connector.26 + + + + Nordic Lake.30 + USB (audio) + + USB (audio) + + Nordic Blue.33 + + + + Sheet.34 + Network core + + Network core + + Sheet.36 + Application core + + Application core + + Nordic Middle Grey.42 + + + + Dynamic connector.75 + + + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.83 + HCI IPC + + HCI IPC + + Sheet.84 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Nordic Blue.88 + + + + Nordic Lake.89 + + + + Dynamic connector.90 + + + + Sheet.91 + Control data + + Control data + + Dynamic connector.93 + + + + Sheet.94 + Compressed audio + + Compressed audio + + Dynamic connector.95 + + + + Sheet.96 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.97 + + + + Sheet.98 + Block working on compressed audio + + Block working on compressed audio + + Sheet.99 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.100 + + + + Sheet.101 + HW layer element + + HW layer element + + Sheet.102 + + Nordic Blue.24 + + + + Sheet.85 + Peripheral modules + + Peripheral modules + + + Nordic Lake.104 + USB RX FIFO + + USB RX FIFO + + Nordic Light Grey + sw_codec_select.c + + sw_codec_select.c + + Nordic Lake.105 + Encoder + + Encoder + + Dynamic connector.109 + + + + Dynamic connector.114 + + + + Nordic Lake.115 + + + + Sheet.116 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.118 + Large main module + + Large main module + + Sheet.119 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Dynamic connector.122 + + + + Nordic Blue.129 + + + + Dynamic connector.134 + + + + Sheet.135 + Bluetooth modules + + Bluetooth modules + + Sheet.136 + main.c + + main.c + + Nordic Blue.124 + + + + Nordic Light Grey.125 + broadcast_source.c + + broadcast_source.c + + diff --git a/doc/nrf/images/nrf5340_audio_structure_generic.svg b/doc/nrf/images/nrf5340_audio_structure_generic.svg new file mode 100644 index 00000000000..c2c9a139883 --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_structure_generic.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + Page-1 + + Sheet.140 + nRF5340 SoC + + nRF5340 SoC + + Sheet.136 + + Nordic Blue.24 + + + + + Sheet.138 + + + + Sheet.130 + + + + Sheet.144 + Application + + Application + + Nordic Blue + Bluetooth LE Host + + Bluetooth LE Host + + Nordic Blue.6 + SoftDevice Controller (LE Isochronous Channels) + + SoftDevice Controller (LE Isochronous Channels) + + Sheet.34 + Network core + + Network core + + Sheet.36 + Application core + + Application core + + Dynamic connector.45 + + + + Dynamic connector.46 + + + + Dynamic connector.68 + + + + Dynamic connector.72 + + + + Dynamic connector.82 + + + + Sheet.83 + HCI RPMSG + + HCI RPMSG + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Sheet.145 + + Sheet.102 + + Nordic Blue.24 + + + + + Sheet.123 + Peripheral modules + + Peripheral modules + + + Sheet.146 + + Nordic Blue.25 + + + + Sheet.84 + Audio modules + + Audio modules + + + Sheet.147 + + Nordic Blue.25 + + + + Sheet.149 + Bluetooth modules + + Bluetooth modules + + + Dynamic connector + + + + Dynamic connector.152 + + + + Dynamic connector.154 + + + + Dynamic connector.155 + + + + diff --git a/doc/nrf/images/nrf5340_audio_structure_sync_module.svg b/doc/nrf/images/nrf5340_audio_structure_sync_module.svg new file mode 100644 index 00000000000..60a7c40084b --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_structure_sync_module.svg @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Middle Grey + + + + Nordic Lake + audio_i2s.c + + audio_i2s.c + + Nordic Blue.25 + + + + Nordic Lake.31 + I2S RX FIFO + + I2S RX FIFO + + Nordic Sky + audio_sync_timer.c + + audio_sync_timer.c + + Nordic Blue.33 + + + + Sheet.34 + RX (HW codec to nRF5340) + + RX (HW codec to nRF5340) + + Sheet.36 + TX (nRF5340 to HW codec) + + TX (nRF5340 to HW codec) + + Sheet.58 + bad_frame + + bad_frame + + Sheet.65 + sdu_ref + + sdu_ref + + Sheet.76 + cur_time + + cur_time + + Sheet.79 + frame_start_ts + + frame_start_ts + + Sheet.84 + Synchronization module (audio_datapath.c) + + Synchronization module (audio_datapath.c) + + Nordic Middle Grey.102 + + + + Nordic Lake.103 + Bluetooth LE RX FIFO + + Bluetooth LE RX FIFO + + Nordic Lake.107 + I2S TX FIFO + + I2S TX FIFO + + Nordic Lake.108 + I2S block complete + + I2S block complete + + Nordic Sky.110 + pcm_mix.c + + pcm_mix.c + + Nordic Light Grey.112 + Presentation compensation (Executed every time a new package ... + + Presentation compensation (Executed every time a new package is received) + + Nordic Light Grey.113 + Drift compensation (Executed every time an I2S block is compl... + + Drift compensation (Executed every time an I2S block is completed) + + Nordic Lake.118 + I2S block complete + + I2S block complete + + Dynamic connector.126 + + + + Dynamic connector.127 + + + + Dynamic connector.129 + + + + Dynamic connector.131 + + + + Dynamic connector.132 + + + + Dynamic connector.133 + + + + Dynamic connector.134 + + + + Dynamic connector.136 + + + + Dynamic connector.137 + + + + Sheet.140 + Estimate current sdu_ref if the delta between the current and... + + Estimate current sdu_ref if the delta between the current and the previous incoming sdu_ref is over or under a threshold + + Sheet.142 + Adjust placement of audio blocks in FIFO to synchronize audio + + Adjust placement of audio blocks in FIFO to synchronize audio + + Dynamic connector.143 + + + + Nordic Lake.144 + Audio clock (PLL) fine adjustment for synchronizing audio + + Audio clock (PLL) fine adjustment for synchronizing audio + + Dynamic connector.145 + + + + Dynamic connector.146 + + + + Dynamic connector.147 + + + + Sheet.169 + + Nordic Light Grey.111 + tone.c + + tone.c + + Nordic Lake.109 + Tone + + Tone + + + Sheet.172 + + Nordic Light Grey + + + + Nordic Lake.37 + Decoder + + Decoder + + + Dynamic connector.121 + + + + Sheet.180 + + Nordic Blue.88 + + + + Nordic Lake.89 + + + + Dynamic connector.90 + + + + Sheet.151 + Control data + + Control data + + Dynamic connector.93 + + + + Sheet.153 + Compressed audio + + Compressed audio + + Dynamic connector.95 + + + + Sheet.155 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.97 + + + + Sheet.157 + Block working on compressed audio + + Block working on compressed audio + + Sheet.158 + Block working on uncompressed audio + + Block working on uncompressed audio + + Sheet.165 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Nordic Lake.173 + + + + Sheet.174 + Adjustments + + Adjustments + + Nordic Lake.177 + + + + Nordic Lake.178 + + + + Sheet.179 + Compensations + + Compensations + + + Dynamic connector + + + + Dynamic connector.120 + + + + Dynamic connector.182 + + + + Sheet.183 + audio_system.c + + audio_system.c + + Sheet.184 + streamctrl_unicast_client.c + + streamctrl_unicast_client.c + + Sheet.185 + streamctrl_unicast_server.c + + streamctrl_unicast_server.c + + Sheet.186 + streamctrl_broadcast_source.c + + streamctrl_broadcast_source.c + + Sheet.187 + streamctrl_broadcast_sink.c + + streamctrl_broadcast_sink.c + + Sheet.188 + sw_codec_select.c + + sw_codec_select.c + + Sheet.190 + One of the following: + + One of the following: + + diff --git a/doc/nrf/images/octave_application_sync_module_states.svg b/doc/nrf/images/nrf5340_audio_sync_module_states.svg similarity index 100% rename from doc/nrf/images/octave_application_sync_module_states.svg rename to doc/nrf/images/nrf5340_audio_sync_module_states.svg diff --git a/doc/nrf/images/nrf5340_audio_unicast_client_I2S_structure.svg b/doc/nrf/images/nrf5340_audio_unicast_client_I2S_structure.svg new file mode 100644 index 00000000000..4454df1d85d --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_unicast_client_I2S_structure.svg @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Dynamic connector.68 + + + + Nordic Middle Grey + audio_system.c + + audio_system.c + + Nordic Light Grey + sw_codec_select.c + + sw_codec_select.c + + Nordic Blue + + + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.13 + HW codec (CS47L63) + + HW codec (CS47L63) + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + Synchronization module (audio_datapath.c) + + Synchronization module (audio_datapath.c) + + Nordic Lake + audio_i2s.c + + audio_i2s.c + + Nordic Blue.25 + + + + Dynamic connector.26 + + + + Dynamic connector.29 + + + + Nordic Lake.30 + I2S (audio) + + I2S (audio) + + Nordic Lake.31 + I2S RX FIFO + + I2S RX FIFO + + Nordic Sky + audio_sync_timer.c + + audio_sync_timer.c + + Nordic Blue.33 + + + + Sheet.264 + Network core + + Network core + + Sheet.265 + Application core + + Application core + + Nordic Lake.37 + Encoder + + Encoder + + Nordic Middle Grey.42 + + + + Dynamic connector.44 + + + + Dynamic connector.45 + + + + Dynamic connector.46 + + + + Dynamic connector.49 + + + + Dynamic connector.50 + + + + Sheet.273 + bad_frame + + bad_frame + + Sheet.274 + sdu_ref + + sdu_ref + + Sheet.275 + bad_frame + + bad_frame + + Sheet.276 + sdu_ref + + sdu_ref + + Dynamic connector.72 + + + + Dynamic connector.73 + + + + Dynamic connector.74 + + + + Dynamic connector.75 + + + + Sheet.281 + cur_time + + cur_time + + Dynamic connector.77 + + + + Sheet.283 + frame_start_ts + + frame_start_ts + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.287 + HCI IPC + + HCI IPC + + Sheet.288 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Sheet.291 + + Nordic Blue.24 + + + + Sheet.293 + Peripheral modules + + Peripheral modules + + + Nordic Blue.103 + + + + Nordic Lake.104 + + + + Dynamic connector.105 + + + + Sheet.297 + Control data + + Control data + + Dynamic connector.107 + + + + Sheet.299 + Compressed audio + + Compressed audio + + Dynamic connector.109 + + + + Sheet.301 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.111 + + + + Sheet.303 + Block working on compressed audio + + Block working on compressed audio + + Sheet.304 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.114 + + + + Sheet.306 + HW layer element + + HW layer element + + Nordic Lake.115 + + + + Sheet.308 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.310 + Large main module + + Large main module + + Sheet.311 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Nordic Lake.123 + + + + Sheet.315 + Synchronization module + + Synchronization module + + Dynamic connector.126 + + + + Nordic Blue.128 + Bluetooth LE Host + + Bluetooth LE Host + + Dynamic connector.129 + + + + Dynamic connector.130 + + + + Dynamic connector.131 + + + + Nordic Blue.129 + + + + Sheet.322 + Bluetooth modules + + Bluetooth modules + + Nordic Light Grey.140 + unicast_client.c + + unicast_client.c + + Dynamic connector.143 + + + + Dynamic connector.48 + + + + Dynamic connector.47 + + + + Nordic Lake.43 + Bluetooth LE RX FIFO + + Bluetooth LE RX FIFO + + Sheet.333 + main.c + + main.c + + Dynamic connector.339 + + + + Sheet.340 + + Nordic Light Grey.335 + sw_codec_select.c + + sw_codec_select.c + + Nordic Lake.336 + Decoder + + Decoder + + + diff --git a/doc/nrf/images/nrf5340_audio_unicast_client_USB_structure.svg b/doc/nrf/images/nrf5340_audio_unicast_client_USB_structure.svg new file mode 100644 index 00000000000..0666db27805 --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_unicast_client_USB_structure.svg @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Nordic Blue + Bluetooth LE Host + + Bluetooth LE Host + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + audio_system.c + + audio_system.c + + Nordic Lake + audio_usb.c + + audio_usb.c + + Nordic Blue.25 + + + + Dynamic connector.26 + + + + Nordic Lake.30 + USB (audio) + + USB (audio) + + Nordic Blue.33 + + + + Sheet.34 + Network core + + Network core + + Sheet.36 + Application core + + Application core + + Nordic Middle Grey.42 + + + + Nordic Lake.43 + Bluetooth LE RX FIFO + + Bluetooth LE RX FIFO + + Dynamic connector.45 + + + + Dynamic connector.46 + + + + Sheet.66 + bad_frame + + bad_frame + + Sheet.71 + sdu_ref + + sdu_ref + + Dynamic connector.72 + + + + Dynamic connector.74 + + + + Dynamic connector.75 + + + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.83 + HCI IPC + + HCI IPC + + Sheet.84 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Nordic Blue.88 + + + + Nordic Lake.89 + + + + Dynamic connector.90 + + + + Sheet.91 + Control data + + Control data + + Dynamic connector.93 + + + + Sheet.94 + Compressed audio + + Compressed audio + + Dynamic connector.95 + + + + Sheet.96 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.97 + + + + Sheet.98 + Block working on compressed audio + + Block working on compressed audio + + Sheet.99 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.100 + + + + Sheet.101 + HW layer element + + HW layer element + + Sheet.102 + + Nordic Blue.24 + + + + Sheet.85 + Peripheral modules + + Peripheral modules + + + Nordic Lake.103 + USB TX FIFO + + USB TX FIFO + + Nordic Lake.104 + USB RX FIFO + + USB RX FIFO + + Nordic Light Grey + sw_codec_select.c + + sw_codec_select.c + + Nordic Lake.105 + Encoder + + Encoder + + Nordic Lake.106 + Decoder + + Decoder + + Dynamic connector.107 + + + + Dynamic connector.109 + + + + Dynamic connector.111 + + + + Sheet.112 + bad_frame + + bad_frame + + Dynamic connector.113 + + + + Dynamic connector.114 + + + + Nordic Lake.115 + + + + Sheet.116 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.118 + Large main module + + Large main module + + Sheet.119 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Dynamic connector.122 + + + + Nordic Blue.129 + + + + Dynamic connector.131 + + + + Dynamic connector.132 + + + + Dynamic connector.133 + + + + Dynamic connector.134 + + + + Sheet.135 + Bluetooth modules + + Bluetooth modules + + Sheet.137 + main.c + + main.c + + Nordic Blue.124 + + + + Nordic Light Grey.126 + unicast_client.c + + unicast_client.c + + diff --git a/doc/nrf/images/nrf5340_audio_unicast_server_I2S_structure.svg b/doc/nrf/images/nrf5340_audio_unicast_server_I2S_structure.svg new file mode 100644 index 00000000000..b6f7077d04e --- /dev/null +++ b/doc/nrf/images/nrf5340_audio_unicast_server_I2S_structure.svg @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Dynamic connector.68 + + + + Nordic Middle Grey + audio_system.c + + audio_system.c + + Nordic Light Grey + sw_codec_select.c + + sw_codec_select.c + + Nordic Blue + + + + Nordic Blue.6 + SoftDevice Controller + + SoftDevice Controller + + Nordic Blue.7 + Radio + + Radio + + Nordic Blue.8 + UART (debug) + + UART (debug) + + Nordic Blue.9 + UART (debug) + + UART (debug) + + Nordic Blue.10 + TWI/I2C + + TWI/I2C + + Nordic Blue.11 + SPI4 + + SPI4 + + Nordic Blue.12 + SD card + + SD card + + Nordic Blue.13 + HW codec (CS47L63) + + HW codec (CS47L63) + + Nordic Blue.14 + Power module (INA231) + + Power module (INA231) + + Nordic Blue.15 + Error handler + + Error handler + + Nordic Blue.16 + Buttons + + Buttons + + Nordic Blue.17 + LEDs + + LEDs + + Dynamic connector + + + + Nordic Blueslate + Synchronization module (audio_datapath.c) + + Synchronization module (audio_datapath.c) + + Nordic Lake + audio_i2s.c + + audio_i2s.c + + Nordic Blue.25 + + + + Dynamic connector.26 + + + + Dynamic connector.29 + + + + Nordic Lake.30 + I2S (audio) + + I2S (audio) + + Nordic Lake.31 + I2S RX FIFO + + I2S RX FIFO + + Nordic Sky + audio_sync_timer.c + + audio_sync_timer.c + + Nordic Blue.33 + + + + Sheet.264 + Network core + + Network core + + Sheet.265 + Application core + + Application core + + Nordic Lake.37 + Encoder + + Encoder + + Nordic Middle Grey.42 + + + + Dynamic connector.44 + + + + Dynamic connector.45 + + + + Dynamic connector.46 + + + + Dynamic connector.49 + + + + Dynamic connector.50 + + + + Sheet.273 + bad_frame + + bad_frame + + Sheet.274 + sdu_ref + + sdu_ref + + Sheet.275 + bad_frame + + bad_frame + + Sheet.276 + sdu_ref + + sdu_ref + + Dynamic connector.72 + + + + Dynamic connector.73 + + + + Dynamic connector.74 + + + + Dynamic connector.75 + + + + Sheet.281 + cur_time + + cur_time + + Dynamic connector.77 + + + + Sheet.283 + frame_start_ts + + frame_start_ts + + Dynamic connector.80 + + + + Dynamic connector.81 + + + + Dynamic connector.82 + + + + Sheet.287 + HCI IPC + + HCI IPC + + Sheet.288 + Audio modules + + Audio modules + + Dynamic connector.86 + + + + Dynamic connector.87 + + + + Sheet.291 + + Nordic Blue.24 + + + + Sheet.293 + Peripheral modules + + Peripheral modules + + + Nordic Blue.103 + + + + Nordic Lake.104 + + + + Dynamic connector.105 + + + + Sheet.297 + Control data + + Control data + + Dynamic connector.107 + + + + Sheet.299 + Compressed audio + + Compressed audio + + Dynamic connector.109 + + + + Sheet.301 + Uncompressed audio + + Uncompressed audio + + Nordic Lake.111 + + + + Sheet.303 + Block working on compressed audio + + Block working on compressed audio + + Sheet.304 + Block working on uncompressed audio + + Block working on uncompressed audio + + Nordic Lake.114 + + + + Sheet.306 + HW layer element + + HW layer element + + Nordic Lake.115 + + + + Sheet.308 + Peripheral module + + Peripheral module + + Nordic Lake.117 + + + + Sheet.310 + Large main module + + Large main module + + Sheet.311 + Application source files + + Application source files + + Nordic Lake.120 + + + + Nordic Lake.121 + + + + Nordic Lake.123 + + + + Sheet.315 + Synchronization module + + Synchronization module + + Dynamic connector.126 + + + + Nordic Blue.128 + Bluetooth LE Host + + Bluetooth LE Host + + Dynamic connector.129 + + + + Dynamic connector.130 + + + + Dynamic connector.131 + + + + Nordic Blue.129 + + + + Sheet.322 + Bluetooth modules + + Bluetooth modules + + Nordic Light Grey.141 + unicast_server.c + + unicast_server.c + + Dynamic connector.143 + + + + Dynamic connector.48 + + + + Dynamic connector.47 + + + + Nordic Lake.43 + Bluetooth LE RX FIFO + + Bluetooth LE RX FIFO + + Sheet.333 + main.c + + main.c + + Sheet.334 + + Nordic Light Grey.335 + sw_codec_select.c + + sw_codec_select.c + + Nordic Lake.336 + Decoder + + Decoder + + + Dynamic connector.337 + + + + diff --git a/doc/nrf/images/octave_application_structure_generic.svg b/doc/nrf/images/octave_application_structure_generic.svg deleted file mode 100644 index 3f838b58afe..00000000000 --- a/doc/nrf/images/octave_application_structure_generic.svg +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - Page-1 - - Sheet.140 - nRF5340 SoC - - nRF5340 SoC - - Sheet.136 - - Nordic Blue.24 - - - - - Sheet.138 - - - - Sheet.130 - - - - Sheet.144 - Application - - Application - - Nordic Blue - Bluetooth LE Host - - Bluetooth LE Host - - Nordic Blue.6 - LE Audio Controller Subsystem for nRF53 - - LE Audio Controller Subsystem for nRF53 - - Sheet.34 - Network core - - Network core - - Sheet.36 - Application core - - Application core - - Dynamic connector.45 - - - - Dynamic connector.46 - - - - Dynamic connector.68 - - - - Dynamic connector.72 - - - - Dynamic connector.82 - - - - Sheet.83 - HCI RPMSG - - HCI RPMSG - - Dynamic connector.86 - - - - Dynamic connector.87 - - - - Sheet.145 - - Sheet.102 - - Nordic Blue.24 - - - - - Sheet.123 - Peripheral modules - - Peripheral modules - - - Sheet.146 - - Nordic Blue.25 - - - - Sheet.84 - Audio modules - - Audio modules - - - Sheet.147 - - Nordic Blue.25 - - - - Sheet.149 - Bluetooth modules - - Bluetooth modules - - - Dynamic connector - - - - Dynamic connector.152 - - - - Dynamic connector.154 - - - - Dynamic connector.155 - - - - diff --git a/doc/nrf/images/octave_application_structure_sync_module.svg b/doc/nrf/images/octave_application_structure_sync_module.svg deleted file mode 100644 index d4dd4c30f1f..00000000000 --- a/doc/nrf/images/octave_application_structure_sync_module.svg +++ /dev/null @@ -1,447 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Page-1 - - Nordic Middle Grey - - - - Sheet.1 - Max 800 px - - - Max 800 px - - Sheet.2 - Max 780 px - - - Max 780 px - - Sheet.3 - - - - Sheet.4 - - - - Nordic Lake - audio_i2s.c - - audio_i2s.c - - Nordic Blue.25 - - - - Nordic Lake.31 - I2S RX FIFO - - I2S RX FIFO - - Nordic Sky - audio_sync_timer.c - - audio_sync_timer.c - - Nordic Blue.33 - - - - Sheet.34 - RX (HW codec to nRF5340) - - RX (HW codec to nRF5340) - - Sheet.36 - TX (nRF5340 to HW codec) - - TX (nRF5340 to HW codec) - - Sheet.58 - bad_frame - - bad_frame - - Sheet.65 - sdu_ref - - sdu_ref - - Sheet.76 - cur_time - - cur_time - - Sheet.79 - frame_start_ts - - frame_start_ts - - Sheet.84 - Synchronization module (audio_datapath.c) - - Synchronization module (audio_datapath.c) - - Nordic Middle Grey.102 - - - - Nordic Lake.103 - Bluetooth LE RX FIFO - - Bluetooth LE RX FIFO - - Nordic Lake.107 - I2S TX FIFO - - I2S TX FIFO - - Nordic Lake.108 - I2S block complete - - I2S block complete - - Nordic Sky.110 - pcm_mix.c - - pcm_mix.c - - Nordic Light Grey.112 - Presentation compensation (Executed every time a new package ... - - Presentation compensation (Executed every time a new package is received) - - Nordic Light Grey.113 - Drift compensation (Executed every time an I2S block is compl... - - Drift compensation (Executed every time an I2S block is completed) - - Nordic Lake.118 - I2S block complete - - I2S block complete - - Dynamic connector.126 - - - - Dynamic connector.127 - - - - Dynamic connector.129 - - - - Dynamic connector.131 - - - - Dynamic connector.132 - - - - Dynamic connector.133 - - - - Dynamic connector.134 - - - - Dynamic connector.136 - - - - Dynamic connector.137 - - - - Sheet.140 - Estimate current sdu_ref if the delta between the current and... - - Estimate current sdu_ref if the delta between the current and the previous incoming sdu_ref is over or under a threshold - - Sheet.142 - Adjust placement of audio blocks in FIFO to synchronize audio - - Adjust placement of audio blocks in FIFO to synchronize audio - - Dynamic connector.143 - - - - Nordic Lake.144 - Audio clock (PLL) fine adjustment for synchronizing audio - - Audio clock (PLL) fine adjustment for synchronizing audio - - Dynamic connector.145 - - - - Dynamic connector.146 - - - - Dynamic connector.147 - - - - Sheet.169 - - Nordic Light Grey.111 - tone.c - - tone.c - - Nordic Lake.109 - Tone - - Tone - - - Sheet.172 - - Nordic Light Grey - - - - Nordic Lake.37 - Decoder - - Decoder - - - Dynamic connector.121 - - - - Sheet.180 - - Nordic Blue.88 - - - - Nordic Lake.89 - - - - Dynamic connector.90 - - - - Sheet.151 - Control data - - Control data - - Dynamic connector.93 - - - - Sheet.153 - Compressed audio - - Compressed audio - - Dynamic connector.95 - - - - Sheet.155 - Uncompressed audio - - Uncompressed audio - - Nordic Lake.97 - - - - Sheet.157 - Block working on compressed audio - - Block working on compressed audio - - Sheet.158 - Block working on uncompressed audio - - Block working on uncompressed audio - - Sheet.165 - Application source files - - Application source files - - Nordic Lake.120 - - - - Nordic Lake.121 - - - - Nordic Lake.173 - - - - Sheet.174 - Adjustments - - Adjustments - - Nordic Lake.177 - - - - Nordic Lake.178 - - - - Sheet.179 - Compensations - - Compensations - - - Dynamic connector - - - - Dynamic connector.120 - - - - Dynamic connector.182 - - - - Sheet.183 - audio_system.c - - audio_system.c - - Sheet.184 - streamctrl_unicast_client.c - - streamctrl_unicast_client.c - - Sheet.185 - streamctrl_unicast_server.c - - streamctrl_unicast_server.c - - Sheet.186 - streamctrl_broadcast_source.c - - streamctrl_broadcast_source.c - - Sheet.187 - streamctrl_broadcast_sink.c - - streamctrl_broadcast_sink.c - - Sheet.188 - sw_codec_select.c - - sw_codec_select.c - - Sheet.190 - One of the following: - - One of the following: - - diff --git a/doc/nrf/images/octave_application_topologies.svg b/doc/nrf/images/octave_application_topologies.svg deleted file mode 100644 index 2d36733d3b5..00000000000 --- a/doc/nrf/images/octave_application_topologies.svg +++ /dev/null @@ -1,3305 +0,0 @@ - - - - - - - - - - - - - - - - - - - Page-1 - - Sheet.172 - - - - Sheet.171 - - - - Sheet.170 - - - - Sheet.122 - - - - Sheet.125 - Connected Isochronous Stream (CIS) - - Connected Isochronous Stream (CIS) - - Sheet.164 - Broadcast Isochronous Stream (BIS) - - Broadcast Isochronous Stream (BIS) - - Sheet.137 - - - - Sheet.135 - - - - Sheet.136 - - - - Dynamic connector.141 - - - - Dynamic connector.142 - - - - Sheet.143 - - - - Sheet.157 - - - - Sheet.140 - - - - Sheet.158 - - - - Dynamic connector.146 - - - - Dynamic connector.147 - - - - Dynamic connector.148 - - - - Dynamic connector.149 - - - - Dynamic connector.150 - - - - Sheet.168 - Any number of receivers - - Any number of receivers - - Sheet.169 - - - - Dynamic connector.173 - - - - Sheet.174 - Synchronized playback - - Synchronized playback - - Sheet.177 - - - - Sheet.176 - - - - - - Sheet.178 - One audio source - - One audio source - - Sheet.180 - - - - - - Sheet.181 - - - - - - Sheet.182 - - - - - - Sheet.183 - - - - - - Sheet.184 - - - - - - Sheet.185 - - - - - - Sheet.186 - - - - - - diff --git a/doc/nrf/test_and_optimize/images/putty.svg b/doc/nrf/images/putty.svg similarity index 100% rename from doc/nrf/test_and_optimize/images/putty.svg rename to doc/nrf/images/putty.svg diff --git a/doc/nrf/test_and_optimize/images/rtt_viewer_configuration.png b/doc/nrf/images/rtt_viewer_configuration.png similarity index 100% rename from doc/nrf/test_and_optimize/images/rtt_viewer_configuration.png rename to doc/nrf/images/rtt_viewer_configuration.png diff --git a/doc/nrf/images/wireshark_decode_as_nordic_80211.png b/doc/nrf/images/wireshark_decode_as_nordic_80211.png new file mode 100644 index 00000000000..b3df739def7 Binary files /dev/null and b/doc/nrf/images/wireshark_decode_as_nordic_80211.png differ diff --git a/doc/nrf/includes/application_build_and_run.txt b/doc/nrf/includes/application_build_and_run.txt index 0b345f9ee74..45fe0c49435 100644 --- a/doc/nrf/includes/application_build_and_run.txt +++ b/doc/nrf/includes/application_build_and_run.txt @@ -1,4 +1,4 @@ This application can be found under |application path| in the |NCS| folder structure. To build the application with |VSC|, follow the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. -See :ref:`programming` for other building and programming scenarios and :ref:`testing` for general information about testing and debugging in the |NCS|. +See :ref:`building` for other building scenarios, :ref:`programming` for programming steps, and :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/application_build_and_run_ns.txt b/doc/nrf/includes/application_build_and_run_ns.txt index 6c254b24a0e..3951676fe2f 100644 --- a/doc/nrf/includes/application_build_and_run_ns.txt +++ b/doc/nrf/includes/application_build_and_run_ns.txt @@ -5,4 +5,4 @@ Because of this, it automatically includes the :ref:`Trusted Firmware-M (TF-M) < To read more about CMSE, see :ref:`app_boards_spe_nspe`. To build the application with |VSC|, follow the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. -See :ref:`programming` for other building and programming scenarios and :ref:`testing` for general information about testing and debugging in the |NCS|. +See :ref:`building` for other building scenarios, :ref:`programming` for programming steps, and :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/build_and_run.txt b/doc/nrf/includes/build_and_run.txt index 0c972e0988e..8378c1f3e7d 100644 --- a/doc/nrf/includes/build_and_run.txt +++ b/doc/nrf/includes/build_and_run.txt @@ -1,4 +1,4 @@ This sample can be found under |sample path| in the |NCS| folder structure. To build the sample with |VSC|, follow the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. -See :ref:`programming` for other building and programming scenarios and :ref:`testing` for general information about testing and debugging in the |NCS|. +See :ref:`building` for other building scenarios, :ref:`programming` for programming steps, and :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/build_and_run_ns.txt b/doc/nrf/includes/build_and_run_ns.txt index e9a9901b13c..a12f488b680 100644 --- a/doc/nrf/includes/build_and_run_ns.txt +++ b/doc/nrf/includes/build_and_run_ns.txt @@ -5,4 +5,4 @@ Because of this, it automatically includes the :ref:`Trusted Firmware-M (TF-M) < To read more about CMSE, see :ref:`app_boards_spe_nspe`. To build the sample with |VSC|, follow the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. -See :ref:`programming` for other building and programming scenarios and :ref:`testing` for general information about testing and debugging in the |NCS|. +See :ref:`building` for other building scenarios, :ref:`programming` for programming steps, and :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/build_and_run_sb.txt b/doc/nrf/includes/build_and_run_sb.txt index bb8e057d71b..dc57b064a64 100644 --- a/doc/nrf/includes/build_and_run_sb.txt +++ b/doc/nrf/includes/build_and_run_sb.txt @@ -17,4 +17,4 @@ If you want to flash only one core, you have to add the ``--domain`` argument: west flash --domain hello_world To build the sample with |VSC|, follow the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. -See :ref:`programming` for other building and programming scenarios and :ref:`testing` for general information about testing and debugging in the |NCS|. +See :ref:`building` for other building scenarios, :ref:`programming` for programming steps, and :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/cert-flashing.txt b/doc/nrf/includes/cert-flashing.txt index 37b3ee7c8d3..56f7d4f680e 100644 --- a/doc/nrf/includes/cert-flashing.txt +++ b/doc/nrf/includes/cert-flashing.txt @@ -1,8 +1,8 @@ -To provision the certificates and the private key to the cellular modem, complete the following steps: +To provision the certificates and the private key to the nRF91 Series modem, complete the following steps: 1. `Download nRF Connect for Desktop`_. #. Update the modem firmware on the onboard modem of the nRF91 Series device to the latest version by following the steps in :ref:`nrf9160_gs_updating_fw_modem`. -#. Build and program the :ref:`at_client_sample` sample to the nRF91 Series device as explained in :ref:`programming`. +#. Build and program the :ref:`at_client_sample` sample to the nRF91 Series device as explained in :ref:`building` and :ref:`programming`. #. Launch the `Cellular Monitor`_ application, which is part of `nRF Connect for Desktop`_. #. Click :guilabel:`CERTIFICATE MANAGER` located at the upper right corner. #. Copy the server root certificate into the ``CA certificate`` entry. diff --git a/doc/nrf/includes/config_build_and_run.txt b/doc/nrf/includes/config_build_and_run.txt index 294c06fe214..6777ebe7034 100644 --- a/doc/nrf/includes/config_build_and_run.txt +++ b/doc/nrf/includes/config_build_and_run.txt @@ -1,4 +1,4 @@ This sample can be found under |sample path| in the |NCS| folder structure. -See :ref:`configure_application` and :ref:`programming` for information about how to configure and how to build and program the application. +See :ref:`building` and :ref:`programming` for information about how to configure and build and how to program the application. Also check :ref:`testing` for general information about testing and debugging in the |NCS|. diff --git a/doc/nrf/includes/lwm2m_common_server_setup.txt b/doc/nrf/includes/lwm2m_common_server_setup.txt index dd8822d092c..5bc5721a585 100644 --- a/doc/nrf/includes/lwm2m_common_server_setup.txt +++ b/doc/nrf/includes/lwm2m_common_server_setup.txt @@ -3,7 +3,7 @@ Server setup The following instructions describe how to register your device to `Leshan Demo Server`_ or `Coiote Device Management server`_: -1. To add the device to the LwM2M server, complete the following steps: +1. To add the device to the LwM2M Server, complete the following steps: .. tabs:: @@ -43,7 +43,7 @@ The following instructions describe how to register your device to `Leshan Demo .. _bootstrap_server_reg: -2. To register the device to an LwM2M bootstrap server, complete the following steps: +2. To register the device to an LwM2M Bootstrap Server, complete the following steps: .. tabs:: @@ -89,6 +89,6 @@ The following instructions describe how to register your device to `Leshan Demo Also, make sure to select the :guilabel:`Key in hexadecimal` checkbox. - The Coiote bootstrap server automatically creates an account for the LwM2M server using the same device endpoint name and random PSK key. + The Coiote Bootstrap server automatically creates an account for the LwM2M Server using the same device endpoint name and random PSK key. #. Click :guilabel:`Add device`. diff --git a/doc/nrf/includes/net_connection_manager.txt b/doc/nrf/includes/net_connection_manager.txt new file mode 100644 index 00000000000..b47c915eae3 --- /dev/null +++ b/doc/nrf/includes/net_connection_manager.txt @@ -0,0 +1,3 @@ +Cellular connectivity is supported on the nRF91 Series SiPs, while |wifi| connectivity is supported on the nRF52 or nRF53 Series SoCs hosting the nRF70 Series Wi-Fi companion ICs. + +The sample uses the :ref:`connection manager ` that provides a common connectivity API for LTE and Wi-Fi stacks. diff --git a/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt b/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt index 5f7d3e1c76f..1effda2a178 100644 --- a/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt +++ b/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt @@ -8,9 +8,11 @@ This sample uses the `nRF Cloud REST API`_, which requires that your device has If you are using nRF9160 DK, modem version v1.3.x or later is required. Your nRF9160 DK may ship with modem firmware older than v1.3.x, so verify that you have the latest installed. +For an nRF9161 DK, modem version v2.0.0 or later is required. For instructions on updating your device's modem firmware, see the following documents: + * :ref:`Updating modem firmware on nRF9161 DK ` * :ref:`Updating modem firmware on nRF9160 DK ` * :ref:`Updating modem firmware on Thingy:91 ` diff --git a/doc/nrf/includes/sample_board_rows.txt b/doc/nrf/includes/sample_board_rows.txt index e8b267c30e3..7b4585dcfee 100644 --- a/doc/nrf/includes/sample_board_rows.txt +++ b/doc/nrf/includes/sample_board_rows.txt @@ -32,9 +32,29 @@ | :ref:`nRF9160 DK ` | PCA10090 | :ref:`nrf9160dk_nrf52840 ` | ``nrf9160dk_nrf52840`` | +.. nrf9161dk_nrf9161 + +| :ref:`nRF9161 DK ` | PCA10153 | :ref:`nrf9161dk_nrf9161 ` | ``nrf9161dk_nrf9161`` | + .. nrf9161dk_nrf9161_ns -| nRF9161 DK | | ``nrf9161dk_nrf9161`` | ``nrf9161dk_nrf9161_ns`` | +| :ref:`nRF9161 DK ` | PCA10153 | :ref:`nrf9161dk_nrf9161 ` | ``nrf9161dk_nrf9161_ns`` | + +.. nrf9131ek_nrf9131 + +| nRF9131 EK | PCA10165 | :ref:`nrf9131ek_nrf9131 ` | ``nrf9131ek_nrf9131`` | + +.. nrf9131ek_nrf9131_ns + +| nRF9131 EK | PCA10165 | :ref:`nrf9131ek_nrf9131 ` | ``nrf9131ek_nrf9131_ns`` | + +.. nrf9151dk_nrf9151 + +| nRF9151 DK | PCA10171 | :ref:`nrf9151dk_nrf9151 ` | ``nrf9151dk_nrf9151`` | + +.. nrf9151dk_nrf9151_ns + +| nRF9151 DK | PCA10171 | :ref:`nrf9151dk_nrf9151 ` | ``nrf9151dk_nrf9151_ns`` | .. nrf5340dk_nrf5340_cpuapp @@ -170,6 +190,18 @@ | :ref:`nRF7002 DK (emulating nRF7001) ` | PCA10143 | :ref:`nrf7002dk_nrf7001_nrf5340 ` | ``nrf7002dk_nrf7001_nrf5340_cpunet`` | +.. nrf54h20dk_nrf54h20_cpuapp + +| :ref:`nRF54H20 DK ` | PCA10175 | :ref:`nrf54h20dk_nrf54h20_cpuapp ` | ``nrf54h20dk_nrf54h20_cpuapp`` | + +.. nrf54h20dk_nrf54h20_cpurad + +| :ref:`nRF54H20 DK ` | PCA10175 | :ref:`nrf54h20dk_nrf54h20_cpurad ` | ``nrf54h20dk_nrf54h20_cpurad`` | + +.. nrf54h20dk_nrf54h20_cpuppr + +| :ref:`nRF54H20 DK ` | PCA10175 | :ref:`nrf54h20dk_nrf54h20_cpuppr ` | ``nrf54h20dk_nrf54h20_cpuppr`` | + .. native_posix | Native Posix | | native_posix | ``native_posix`` | @@ -177,3 +209,11 @@ .. native_sim | Native Simulator | | native_sim | ``native_sim`` | + +.. nrf54l15pdk_nrf54l15_cpuapp + +| :ref:`nRF54L15 PDK ` | PCA10156 | :ref:`nrf54l15pdk_nrf54l15 ` | ``nrf54l15pdk_nrf54l15_cpuapp`` | + +.. nrf54l15pdk_nrf54l15_cpuapp_ns + +| :ref:`nRF54L15 PDK ` | PCA10156 | :ref:`nrf54l15pdk_nrf54l15 ` | ``nrf54l15pdk_nrf54l15_cpuapp_ns`` | diff --git a/doc/nrf/includes/vsc_build_and_run.txt b/doc/nrf/includes/vsc_build_and_run.txt index 112cdee0bbe..e7dae870b4a 100644 --- a/doc/nrf/includes/vsc_build_and_run.txt +++ b/doc/nrf/includes/vsc_build_and_run.txt @@ -1,5 +1,2 @@ -1. Open |VSC|. - - If you installed the |NCS| using the :ref:`auto_installation` steps, you can click the :guilabel:`Open VS Code` button next to the version you installed. - +1. Open the |nRFVSC|. #. Complete the steps listed on the `How to build an application`_ page in the |nRFVSC| documentation. diff --git a/doc/nrf/installation.rst b/doc/nrf/installation.rst index 573019b650f..9023374896d 100644 --- a/doc/nrf/installation.rst +++ b/doc/nrf/installation.rst @@ -29,6 +29,6 @@ This repository is the manifest repository, because it contains the SDK's :ref:` :maxdepth: 2 :caption: Subpages: - installation/recommended_versions installation/install_ncs installation/updating + installation/recommended_versions diff --git a/doc/nrf/installation/install_ncs.rst b/doc/nrf/installation/install_ncs.rst index 031fe61e760..79531d10314 100644 --- a/doc/nrf/installation/install_ncs.rst +++ b/doc/nrf/installation/install_ncs.rst @@ -17,13 +17,20 @@ There are different ways to install the |NCS|, depending on your preferred devel Regardless of which way you choose, the following steps install the |NCS| source code and the |NCS| :term:`toolchain`. This includes everything that is required by Zephyr's :ref:`zephyr:getting_started` together with additional tools and Python dependencies that the |NCS| uses. +Using |VSC| and the |nRFVSC| is also covered in the `Installing nRF Connect SDK and VS Code`_ exercise of the `nRF Connect SDK Fundamentals course`_ on Nordic Developer Academy. + .. rst-class:: numbered-step Update operating system *********************** Before you start setting up the toolchain, install available updates for your operating system. -See :ref:`requirements` for information on the supported operating systems. + +.. include:: ./recommended_versions.rst + :start-after: os_table_start + :end-before: os_table_end + +See :ref:`supported_OS` for more information about the tier definitions. .. _installing_vsc: @@ -32,16 +39,16 @@ See :ref:`requirements` for information on the supported operating systems. Install prerequisites ********************* -Depending on your preferred development environment, install the following tools: +Depending on your preferred development environment, install the following required tools: .. tabs:: .. group-tab:: nRF Connect for Visual Studio Code - * The latest version of |VSC| for your operating system from the `Visual Studio Code download page`_. - * In |VSC|, the latest version of the `nRF Connect for VS Code Extension Pack`_. * The latest version of the :ref:`requirements_clt` package. Download it from the `nRF Command Line Tools`_ page. + * The latest version of |VSC| for your operating system from the `Visual Studio Code download page`_. + * In |VSC|, the latest version of the `nRF Connect for VS Code Extension Pack`_. .. group-tab:: Command line @@ -77,8 +84,7 @@ Depending on your preferred development environment, complete the following step .. group-tab:: nRF Connect for Visual Studio Code 1. Open the nRF Connect extension in |VSC| by clicking its icon in the :guilabel:`Activity Bar`. - #. In the extension's :guilabel:`Welcome View`, click on :guilabel:`Manage toolchains`. - #. In the SDK management menu, click :guilabel:`Install Toolchain`. + #. In the extension's :guilabel:`Welcome View`, click on :guilabel:`Install Toolchain`. #. Select the toolchain version to install. The toolchain version should match the |NCS| version you are going to work with. If you have received a custom URL for installing the toolchain, you can provide it using the :guilabel:`Change Toolchain Index` button in the quick pick's header. @@ -86,6 +92,8 @@ Depending on your preferred development environment, complete the following step When you install the toolchain for the first time, the installed version is automatically selected for your project. + After installing the toolchain, you can access the :guilabel:`Install Toolchain` option by clicking on :guilabel:`Manage toolchains`. + .. group-tab:: Command line 1. Open a terminal window. @@ -309,7 +317,7 @@ Set up the command-line build environment This step is only required when working on command line with freestanding applications. In addition to the steps mentioned above, if you want to build and program your application from the command line, you have to set up your command-line build environment by defining the required environment variables every time you open a new command-line or terminal window. -See :ref:`zephyr:important-build-vars` for more information about the various relevant environment variables. +See :ref:`zephyr:env_vars_important` in the Zephyr documentation for more information about the various relevant environment variables. Define the required environment variables as follows, depending on your operating system: @@ -582,7 +590,7 @@ Legacy installation with Toolchain Manager Toolchain Manager is a tool available from `nRF Connect for Desktop`_, a cross-platform tool that provides different applications that simplify installing the |NCS|. Both the tool and the application are available for Windows, Linux, and macOS. - To install the toolchain and the SDK using the the Toolchain Manager app, complete the following steps: + To install the toolchain and the SDK using the Toolchain Manager app, complete the following steps: 1. Install Toolchain Manager: diff --git a/doc/nrf/installation/recommended_versions.rst b/doc/nrf/installation/recommended_versions.rst index 72f0c51c567..d83ffa8663f 100644 --- a/doc/nrf/installation/recommended_versions.rst +++ b/doc/nrf/installation/recommended_versions.rst @@ -1,18 +1,27 @@ .. _gs_recommended_versions: .. _requirements: -.. _gs_supported_OS: -.. _supported_OS: -Requirements -############ +Requirements reference +###################### .. contents:: :local: :depth: 2 +This page summarizes the requirements for installing and working with the |NCS|. +All of these requirements are installed when you :ref:`install the nRF Connect SDK `. + +.. _gs_supported_OS: +.. _supported_OS: + +Supported operating systems +*************************** + The |NCS| supports Microsoft Windows, Linux, and macOS for development. The following table shows the operating system versions that support the |NCS| tools: +.. os_table_start + .. list-table:: :header-rows: 1 @@ -30,29 +39,35 @@ The following table shows the operating system versions that support the |NCS| t - Not supported * - `Linux - Ubuntu 22.04 LTS`_ - Not supported - - Tier 3 + - Tier 1 - Not supported * - `Linux - Ubuntu 20.04 LTS`_ - Not supported - - Tier 1 + - Tier 2 - Not supported - * - `macOS 13`_ + * - `macOS 14`_ - Not applicable - Tier 3 - Tier 3 + * - `macOS 13`_ + - Not applicable + - Tier 1 + - Tier 1 * - `macOS 12`_ - Not applicable - - Tier 2 - - Tier 2 + - Tier 3 + - Tier 3 * - `macOS 11`_ - Not applicable - - Tier 1 - - Not supported + - Tier 2 + - Tier 2 * - `macOS 10.15`_ - Not applicable - Tier 3 - Not supported +.. os_table_end + Tier definitions The table uses several tier definitions to categorize the level of operating system support: @@ -91,6 +106,7 @@ Zephyr features only available on Linux *************** The |NCS| :term:`toolchain` includes the Zephyr SDK and adds the necessary tools and modules to create |NCS| samples and applications on top of it. +The |NCS| toolchain is installed as one of the steps when :ref:`install_ncs`. .. note:: @@ -183,32 +199,35 @@ Other versions might also work, but are not verified. * - :ref:`west ` - :ncs-tool-version:`WEST_VERSION_DARWIN` -To check the list of installed packages and their versions, run the following command: +Checking tool versions + .. toggle:: -.. tabs:: + To check the list of installed packages and their versions, run the following command: - .. group-tab:: Windows + .. tabs:: - .. code-block:: console + .. group-tab:: Windows - choco list -lo + .. code-block:: console - .. group-tab:: Linux + choco list -lo - .. code-block:: console + Chocolatey is installed as part of the Zephyr SDK toolchain when you :ref:`install the nRF Connect SDK `. - apt list --installed + .. group-tab:: Linux - This command lists all packages installed on your system. - To list the version of a specific package, type its name and add ``--version``. + .. code-block:: console - .. group-tab:: macOS + apt list --installed - .. code-block:: console + This command lists all packages installed on your system. + To list the version of a specific package, type its name and add ``--version``. - brew list --versions + .. group-tab:: macOS + .. code-block:: console + brew list --versions .. _requirements_toolchain_python_deps: @@ -265,8 +284,8 @@ Building and running applications, samples, and tests Building documentation ---------------------- -Python documentation dependencies are listed in the following table. They can -all be installed using the ``doc/requirements.txt`` file using ``pip``. +Python documentation dependencies are listed in the following table. +They can all be installed using the ``doc/requirements.txt`` file using ``pip``. .. list-table:: :header-rows: 1 @@ -318,12 +337,15 @@ Among others, this package includes the following prerequisites for the |NCS|: * nrfjprog executable and library, which the west command uses by default to program the development kits. For more information on nrfjprog, see `Programming SoCs with nrfjprog`_. +It is recommended to use the latest version of the package when you :ref:`installing_vsc`. + .. _toolchain_management_tools: |NCS| toolchain management tools ******************************** Nordic Semiconductor provides proprietary |NCS| toolchain management tools that streamline the process of installing the |NCS| and its toolchain. +Depending on your development environment, you need to install only some of them when you :ref:`installing_vsc`. |nRFVSC| ======== diff --git a/doc/nrf/integrations.rst b/doc/nrf/integrations.rst index 61a169d05de..7ee011f6e4c 100644 --- a/doc/nrf/integrations.rst +++ b/doc/nrf/integrations.rst @@ -22,3 +22,4 @@ The following user guides describe available integrations: external_comp/memfault external_comp/avsystem external_comp/nrf_cloud + external_comp/coremark diff --git a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/API_documentation.rst b/doc/nrf/libraries/bin/bt_ll_acs_nrf53/API_documentation.rst deleted file mode 100644 index 51243f097ae..00000000000 --- a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/API_documentation.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _lib_bt_ll_acs_nrf53_api: - -API documentation -***************** - -.. contents:: - :local: - :depth: 2 - -| Header file: :file:`lib/bin/bt_ll_acs_nrf53/include/ble_hci_vsc.h` -| Source files: :file:`lib/bin/bt_ll_acs_nrf53/src/ble_hci_vsc.c` - -.. doxygengroup:: ble_hci_vsc_api - :project: nrf - :members: diff --git a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/CHANGELOG.rst b/doc/nrf/libraries/bin/bt_ll_acs_nrf53/CHANGELOG.rst deleted file mode 100644 index 4ec0c281399..00000000000 --- a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/CHANGELOG.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. _bt_ll_acs_nrf53_changelog: - -Changelog -######### - -.. contents:: - :local: - :depth: 2 - -Notable changes to this controller are documented in this file. - -Controller v3424 -**************** - -The following changes have been introduced in the v3424 of the controller: - -Changes -======= - -* Improved robustness of the timestamps (the SDU references) received together with the ISO data. -* Changed offset of the timestamps (the SDU references) received together with the ISO data to get correct presentation delay. -* Freed more pins for front-end module (FEM) control. -* Improved ACL and BIS coexistence on the same device. -* Fixed an issue where the peripheral did not always accept timing values from the same central. -* Fixed an issue where the PA sync skip parameter was not used. -* Fixed an issue where it was not possible to create BIG sync after terminating a pending BIG sync. - -Controller v3393 -**************** - -The following changes have been introduced in the v3393 of the controller: - -Changes -======= - -* Updated the controller code with major changes that improve performance on many levels. -* Fixed all failing EBQ tests for claiming the QDID. -* Fixed an issue where the timing of the TXEN FEM pin was wrong and would cause unwanted radio noise. -* Fixed timestamps that are returned when using the LE_READ_ISO_TX_SYNC HCI command. - - -Controller v3357 -**************** - -The following changes have been introduced in the v3357 of the controller: - -Changes -======= - -* Updated the controller to be able to read RSSI from the CIS ISO channel using the ``HCI_Read_RSSI`` HCI command. -* Fixed an issue where pins P0.28 to P0.31 cannot be allocated for controlling front-end modules (FEMs). -* Fixed an issue where the FEM control pins cannot work when the TX output power setting equals 0 dBm. - - -Controller v3349 -**************** - -The following changes have been introduced in the v3349 of the controller: - -Changes -======= - -* Fixed the Direct Test Mode (DTM), which was broken after version 3307. -* Fixed an issue where an update to the connection parameter could lead to a disconnection. -* Fixed an issue where the "stream stopped" and "disconnected" events would not be triggered. -* Fixed an issue where the controller would stop responding when a disconnection happened. - - -Controller v3330 -**************** - -The following changes have been introduced in the v3330 of the controller: - -Changes -======= - -* Fixed issue where resetting one headset caused the other to disconnect. - - -Controller v3322 -**************** - -The following changes have been introduced in the v3322 of the controller: - -Changes -======= - -* Improvements to support creating CIS connections in any order. -* Changes to accommodate BIS + ACL combinations. -* Basic support for interleaved broadcasts. - - -Known issues -************ - -See the :ref:`nRF5340 Audio application known issues ` for the list of known issues for the controller. - - -Limitations -*********** - -The controller is closely related to the nRF5340 Audio application. -See the :ref:`nRF5340 Audio application feature support table ` for the list of supported features and limitations. diff --git a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/index.rst b/doc/nrf/libraries/bin/bt_ll_acs_nrf53/index.rst deleted file mode 100644 index e892ea93b65..00000000000 --- a/doc/nrf/libraries/bin/bt_ll_acs_nrf53/index.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. _lib_bt_ll_acs_nrf53_readme: - -LE Audio controller for nRF5340 -############################### - -.. contents:: - :local: - :depth: 2 - -The LE Audio controller for nRF5340 is a link layer controller for the nRF5340 network core and is meant to be used with LE Audio applications. - -This controller is compatible with the HCI RPMsg driver provided by the |NCS| Bluetooth® :ref:`bt_hci_drivers` core. -When the communication between the application and the network core on a device is handled by the HCI RPMsg driver, this link layer controller can be used to handle time critical low level communication and the radio. - -.. note:: - The LE Audio controller for nRF5340 is under development and is provided in the :ref:`experimental state `. - Make sure to always use the latest version of the controller. - -.. le_audio_controller_qdid_start - -LE Audio controller for nRF5340 QDID - The LE Audio controller for nRF5340 associated with this version of the |NCS| comes with the QDID #181316. - -.. le_audio_controller_qdid_end - -Configuration -************* - -The controller can be enabled with the :Kconfig:option:`CONFIG_BT_LL_ACS_NRF53` set to ``y``. - -The number of Connected Isochronous Streams (CIS) you can use in a Connected Isochronous Group (CIG) and the number of Broadcast Isochronous Streams (BIS) you can use in a Broadcast Isochronous Group (BIG) are dependent on which configurations you use. -The most relevant configurations are bitrate and number of retransmissions. -See the `Capabilities for the LE Audio Controller Subsystem for nRF5340`_ document for matrix tables listing the supported CIS in a CIG and the supported BIS in a BIG. -These matrix tables are based on the Basic Audio Profile (BAP) tables. - -The controller has the following methods of configuration: - -* Standard Host-Controller Interface (HCI) commands -* Vendor-Specific commands (VSC) - -These are listed in :file:`ble_hci_vsc.h`. -See the :ref:`lib_bt_ll_acs_nrf53_api` for more information. - -Usage -***** - -This controller is provided as a HEX file and includes the LE Audio Controller Subsystem for nRF53. -Check the license file in the :file:`/bin` directory for usage conditions. - -The HEX file is to be used with the |NCS| version it is delivered with. -Other combinations are not tested and their behavior is undefined. - -When using the file, the controller is programmed to the network core of nRF5340. -Configurations and calls are handled through standard HCI and VSC. - -Samples using the library -************************* - -The :ref:`nrf53_audio_app` application uses the controller. - -Files -***** - -The network core for both gateway and headsets of the :ref:`nrf53_audio_app` is programmed with the precompiled Bluetooth Low Energy Controller binary file :file:`ble5-ctr-rpmsg_.hex`, where ** corresponds to the controller version, for example :file:`ble5-ctr-rpmsg_3216.hex`. -This file includes the LE Audio Controller Subsystem for nRF53. -If :ref:`DFU is enabled `, the subsystem's binary file will be generated in the :file:`build/zephyr/` directory and will be called :file:`net_core_app_signed.hex`. - -There are two other files in the :file:`/bin` directory: - -* :file:`ble5-ctr-rpmsg_shifted_.hex` which has been shifted to make space for MCUboot. -* :file:`ble5-ctr-rpmsg_shifted_min_.hex` which is the same as above, but made for minimum MCUboot. - -Also for these files, ** corresponds to the controller version. - -Limitations -*********** - -The controller is marked as :ref:`experimental `. - -This controller and the LE Audio Controller Subsystem for nRF5340 it includes has been tested and works in configurations used by the :ref:`nrf53_audio_app` application (for example, 2 concurrent CIS, or BIS). -No other configurations than the ones used in the referenced application have been tested or documented for this library. - -When you :ref:`build the nRF5340 Audio application with the nRF21540 FEM support `, the LE Audio controller for nRF5340 does not support the +20 dBm setting. -This is because of a power class restriction in the controller's QDID. - -Dependencies -************ - -As the controller is provided precompiled in a binary format, there are no software dependencies. -In terms of hardware, this controller is only compatible with the nRF5340. - -.. toctree:: - :maxdepth: 1 - :caption: Subpages: - - API_documentation - CHANGELOG diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/API_documentation.rst b/doc/nrf/libraries/bin/lwm2m_carrier/API_documentation.rst index 6305fbedf0e..71c88345e3a 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/API_documentation.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/API_documentation.rst @@ -23,3 +23,10 @@ LwM2M OS layer .. doxygengroup:: lwm2m_carrier_os :project: nrf :members: + +LwM2M OS DFU image type +======================= + +.. doxygengroup:: lwm2m_os_dfu_img_type + :project: nrf + :members: diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst b/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst index 1161d08ab1d..55de8143642 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst @@ -9,35 +9,84 @@ Changelog All notable changes to this project are documented in this file. -liblwm2m_carrier 3.3.3 +Certification status +==================== + +For certification status of the released versions, see `Mobile network operator certifications`_. + +liblwm2m_carrier 3.4.0 ********************** -Release for modem firmware version 1.3.5 and 2.0.0. +Release for modem firmware version 1.3.6 and 2.0.1. -Certification status -==================== +Size +==== -For certification status, see `Mobile network operator certifications`_. +See :ref:`lwm2m_lib_size` for an explanation of the library size in different scenarios. + ++-------------------------+---------------+------------+ +| | Flash (Bytes) | RAM (Bytes)| ++-------------------------+---------------+------------+ +| Library size | 77020 | 19435 | +| (binary) | | | ++-------------------------+---------------+------------+ +| Library size | 97252 | 34088 | +| (reference application) | | | ++-------------------------+---------------+------------+ Changes ======= -* Minor fixes and improvements. +* Removed AT&T support. + The LwM2M carrier library is no longer required to certify with AT&T. -liblwm2m_carrier 3.3.2 +* Added preliminary support for Bell Canada subscriber ID. + This carrier can be disabled or enabled with the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_BELL_CA`. + +* Changed the default string of the Device Type resource to say "Module" instead of "Smart Device". + This can be changed to other strings using the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_DEVICE_TYPE`. + +* Added ``disable_queue_mode`` to the configuration :c:macro:`lwm2m_carrier_config_t`. + Queue Mode can now be disabled using the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_QUEUE_MODE`. + +* Added a timeout to abort Push FOTA operations using the :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT` Kconfig option. + By default (0), the timer is disabled for unknown subscriber IDs, and set to 30 minutes for the SoftBank subscriber ID. + +* Added the function :c:func:`lwm2m_carrier_data_send`. + This function can be used to send Binary App Data Container and Event Log object data. + + * Renamed the old ``lwm2m_carrier_app_data_send`` function to :c:func:`lwm2m_carrier_app_data_set` to avoid confusion with the new :c:func:`lwm2m_carrier_data_send` function. + The name now also matches the similar function :c:func:`lwm2m_carrier_log_data_set`. + +* The :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_SEC_TAG` Kconfig option can now be used to provide a PSK Identity. + If a PSK Identity is stored in the configured security tag, the LwM2M carrier library makes use of it alongside the PSK. + This behavior does not apply when the device is in the Verizon network, in which case the PSK Identity is overwritten. + +* The FOTA implementation was reworked to use the :ref:`lib_dfu_target` library to manage the DFU process, providing a single interface to support different types of firmware upgrades. + Consequently, the LwM2M carrier library can now perform generic application FOTA. + +* Removed the firmware update type member ``type`` from the :c:struct:`lwm2m_carrier_event_fota_start_t` structure. + The image type is now determined when the LwM2M carrier library calls the glue layer function :c:func:`lwm2m_os_dfu_img_type`. + +liblwm2m_carrier 3.3.3 ********************** Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== +Changes +======= -For certification status, see `Mobile network operator certifications`_. +* Minor fixes and improvements. + +liblwm2m_carrier 3.3.2 +********************** + +Release for modem firmware version 1.3.5 and 2.0.0. Changes ======= -* Fixed an issue where failed modem firmware updates would not be reported correctly to the user application and the LwM2M server. +* Fixed an issue where failed modem firmware updates would not be reported correctly to the user application and the LwM2M Server. liblwm2m_carrier 3.3.1 @@ -45,11 +94,6 @@ liblwm2m_carrier 3.3.1 Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -60,11 +104,6 @@ liblwm2m_carrier 3.3.0 Release for modem firmware version 1.3.5 and 2.0.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -94,7 +133,7 @@ Changes * New successful event flow: :c:member:`LWM2M_CARRIER_EVENT_FOTA_START` > :c:member:`LWM2M_CARRIER_EVENT_LTE_POWER_OFF` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_SHUTDOWN` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_FOTA_SUCCESS` > :c:member:`LWM2M_CARRIER_EVENT_LTE_LINK_UP`. AT&T support has been deprecated --------------------------------- +================================ The application must no longer connect to the AT&T Device Management server. Consequently, the LwM2M carrier library is no longer required to certify with AT&T. @@ -110,11 +149,6 @@ liblwm2m_carrier 3.2.0 Release for modem firmware version 1.3.5. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -155,7 +189,7 @@ Changes * New successful event flow: :c:member:`LWM2M_CARRIER_EVENT_FOTA_START` > :c:member:`LWM2M_CARRIER_EVENT_LTE_POWER_OFF` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_SHUTDOWN` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_MODEM_INIT` > :c:member:`LWM2M_CARRIER_EVENT_FOTA_SUCCESS` > :c:member:`LWM2M_CARRIER_EVENT_LTE_LINK_UP`. nRF modem dependency change ---------------------------- +=========================== LwM2M carrier library no longer explicitly controls the :ref:`nrf_modem`. Instead, the application can initialize the Modem library at its own convenience. @@ -187,11 +221,6 @@ liblwm2m_carrier 3.1.0 Release for modem firmware version 1.3.3 and 1.3.4. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -289,7 +318,7 @@ Changes * This optional value can be left empty to use the default binding (UDP). * Added the new Kconfig :kconfig:option:`CONFIG_LWM2M_SERVER_BINDING_CHOICE`. - * The binding can be either ``U`` (UDP) or ``N`` (Non-IP). + * The binding can be either ``U`` (UDP) or ``N`` (non-IP). * Added the function :c:func:`lwm2m_carrier_request`. @@ -306,11 +335,6 @@ liblwm2m_carrier 0.30.2 Release for modem firmware version 1.3.3. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -338,11 +362,6 @@ liblwm2m_carrier 0.30.1 Release for modem firmware version 1.3.3. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -353,11 +372,6 @@ liblwm2m_carrier 0.30.0 Release for modem firmware version 1.3.1 and 1.3.2. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -438,11 +452,6 @@ liblwm2m_carrier 0.22.0 Release for modem firmware version 1.3.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -475,11 +484,6 @@ liblwm2m_carrier 0.21.0 Release for modem firmware version 1.3.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -501,7 +505,7 @@ Changes * Library can now be provided a non-bootstrap custom URI. Previously, only bootstrap custom URI was accepted. * New Kconfig :kconfig:option:`CONFIG_LWM2M_CARRIER_IS_SERVER_BOOTSTRAP` indicates if the custom URI is a Bootstrap-Server. - * New Kconfig :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_LIFETIME` sets the lifetime for the (non-bootstrap) LwM2M server. + * New Kconfig :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_LIFETIME` sets the lifetime for the (non-bootstrap) LwM2M Server. * Library will now read bootstrap information from Smartcard when applicable. * New Kconfig :kconfig:option:`CONFIG_LWM2M_CARRIER_BOOTSTRAP_SMARTCARD` can be used to disable this feature. @@ -519,11 +523,6 @@ liblwm2m_carrier 0.20.1 Release for modem firmware version 1.3.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -549,11 +548,6 @@ liblwm2m_carrier 0.20.0 Release for modem firmware version 1.3.0. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -562,7 +556,7 @@ Changes * Application is now expected to store CA certificates into the modem security tags. * Added a new event :c:macro:`LWM2M_CARRIER_EVENT_CERTS_INIT` that instructs the application to provide the CA certificate security tags to the LwM2M carrier library. * Renamed the event :c:macro:`LWM2M_CARRIER_BSDLIB_INIT` to :c:macro:`LWM2M_CARRIER_EVENT_MODEM_INIT`. -* Added a new deferred event reason :c:macro:`LWM2M_CARRIER_DEFERRED_SERVICE_UNAVAILABLE`, which indicates that the LwM2M server is unavailable due to maintenance. +* Added a new deferred event reason :c:macro:`LWM2M_CARRIER_DEFERRED_SERVICE_UNAVAILABLE`, which indicates that the LwM2M Server is unavailable due to maintenance. * Added a new error code :c:macro:`LWM2M_CARRIER_ERROR_CONFIGURATION` which indicates that an illegal object configuration was detected. * Added new Kconfig options :kconfig:option:`CONFIG_LWM2M_CARRIER_USE_CUSTOM_APN` and :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_APN` to set the ``apn`` member of :c:type:`lwm2m_carrier_config_t`. * It is now possible to configure a custom bootstrap URI using :kconfig:option:`CONFIG_LWM2M_CARRIER_USE_CUSTOM_BOOTSTRAP_URI` regardless of operator SIM. @@ -572,11 +566,6 @@ liblwm2m_carrier 0.10.2 Release for modem firmware versions 1.2.3 and 1.1.4, and |NCS| 1.4.2. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Size ==== @@ -603,11 +592,6 @@ liblwm2m_carrier 0.10.1 Release for modem firmware versions 1.2.2 and 1.1.4, and |NCS| 1.4.1. -Certification status -==================== - -For certification status, see `Mobile network operator certifications`_. - Changes ======= @@ -624,11 +608,6 @@ Modem firmware version 1.1.4 must be used for Verizon, and the modem firmware ve The snapshot can be used for development and testing only. It is not ready for certification. -Certification status -==================== - -The library is not certified with any carrier. - Changes ======= @@ -643,11 +622,6 @@ liblwm2m_carrier 0.9.1 Release with AT&T support, intended for modem firmware version 1.2.1 and |NCS| version 1.3.1. -Certification status -==================== - -The library is certified with AT&T. - Size ==== @@ -677,11 +651,6 @@ This release is intended to let users begin integration towards the AT&T and Ver It can be used for development and testing only. It is not ready for certification. -Certification status -==================== - -The library is not certified with any carrier. - Changes ======= @@ -704,11 +673,6 @@ liblwm2m_carrier 0.8.2 Release for modem firmware version 1.1.2, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -736,11 +700,6 @@ liblwm2m_carrier 0.8.1+build1 Release for modem firmware version 1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -766,11 +725,6 @@ liblwm2m_carrier 0.8.1 Release for modem firmware version 1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is certified with Verizon Wireless. - Changes ======= @@ -796,11 +750,6 @@ liblwm2m_carrier 0.8.0 Release for modem firmware version 1.1.0 and |NCS| v1.1.0, with support for Verizon Wireless. -Certification status -==================== - -The library is not certified with Verizon Wireless. - Changes ======= @@ -820,7 +769,7 @@ Changes The application must set and maintain these values to reflect the state of the device. Updated values are pushed to the servers autonomously. -* Added API to set the "Device Type" resource. If not set, this is reported as "Smart Device". +* Added API to set the ``Device Type`` resource. If not set, this is reported as ``Smart Device``. * Added API to set the "Software Version" resource. If not set, this is reported as "LwM2M 0.8.0". * Added API to set the "Hardware Version" resource. If not set, this is reported as "1.0". diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst b/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst index f29693cae57..d83c95325f8 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/app_integration.rst @@ -104,7 +104,7 @@ Following are some of the general Kconfig options that you can configure: * The default value is ``IPV4V6``. * If :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_APN` is not set, this configuration is ignored. -* :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`, :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`, :kconfig:option:`CONFIG_LWM2M_CARRIER_ATT`, :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`, :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`, :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`: +* :kconfig:option:`CONFIG_LWM2M_CARRIER_GENERIC`, :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON`, :kconfig:option:`CONFIG_LWM2M_CARRIER_BELL_CA`, :kconfig:option:`CONFIG_LWM2M_CARRIER_LG_UPLUS`, :kconfig:option:`CONFIG_LWM2M_CARRIER_T_MOBILE`, :kconfig:option:`CONFIG_LWM2M_CARRIER_SOFTBANK`: * These configurations allow you to choose the networks in which the carrier library will apply. * For example, if you are deploying a product in several networks but only need to enable the carrier library within Verizon, you must set :kconfig:option:`CONFIG_LWM2M_CARRIER_VERIZON` to ``y`` and all the others to ``n``. @@ -123,6 +123,18 @@ Following are some of the general Kconfig options that you can configure: .. note:: Application DFU is needed to enable LG U+ functionality. +* :kconfig:option:`CONFIG_LWM2M_CARRIER_FIRMWARE_DOWNLOAD_TIMEOUT`: + + * This configuration specifies the time (in minutes) allowed for a single firmware image download. + * If the download is not completed by the time the specified number of minutes elapses, the download shall be aborted. + * This configuration is only supported for Push delivery method of firmware images. + * Leaving this configuration empty (``0``) disables the timer for unknown subscriber IDs, and set it to 30 minutes for the SoftBank subscriber ID. + +* :kconfig:option:`CONFIG_LWM2M_CARRIER_QUEUE_MODE`: + + * This configuration specifies whether the LwM2M device is to inform the LwM2M Server that it may be disconnected for an extended period of time. + + .. _server_options_lwm2m: Server options @@ -153,13 +165,14 @@ The server settings can put the LwM2M carrier library either in the normal mode * :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_LIFETIME`: - * This configuration specifies the lifetime of the custom LwM2M server. + * This configuration specifies the lifetime of the custom LwM2M Server. * This configuration is ignored if :kconfig:option:`CONFIG_LWM2M_CARRIER_IS_BOOTSTRAP_SERVER` is set. * :kconfig:option:`CONFIG_LWM2M_SERVER_BINDING_CHOICE`: - * The binding can be either ``U`` (UDP) or ``N`` (Non-IP). + * The binding can be either ``U`` (UDP) or ``N`` (non-IP). * Leaving this configuration empty selects the default binding (UDP). + * If non-IP binding is configured, :kconfig:option:`CONFIG_LWM2M_CARRIER_CUSTOM_URI` is not used and must be left empty. .. _device_options_lwm2m: @@ -402,7 +415,7 @@ Objects ******* The objects enabled depend on the carrier network. -When connecting to a generic LwM2M server, the following objects are enabled: +When connecting to a generic LwM2M Server, the following objects are enabled: * Security * Server @@ -429,11 +442,11 @@ The following values that reflect the state of the device must be kept up to dat * Battery Status - Defaults to ``5`` if not set (Not Installed). * Memory Total - Defaults to ``0`` if not set. * Error Code - Defaults to ``0`` if not set (No Error). -* Device Type - Defaults to ``Smart Device`` if not set. +* Device Type - Defaults to ``Module`` if not set. * Software Version - Defaults to ``LwM2M ``. - For example, ``LwM2M carrier 3.2.0`` for release 3.2.0. + For example, ``LwM2M carrier 3.4.0`` for release 3.4.0. * Hardware Version - Default value is read from the modem. - An example value is ``nRF9160 SICA B0A``. + An example value is ``nRF9161 LACA ADA``. * Location - Defaults to ``0`` if not set. The following values are read from the modem by default but can be overwritten: @@ -446,3 +459,17 @@ The following values are read from the modem by default but can be overwritten: For example, the carrier device management platform can observe the battery level of your device. The application uses the :c:func:`lwm2m_carrier_battery_level_set` function to indicate the current battery level of the device to the carrier. + +DFU interface +************* + +The LwM2M carrier library makes use of the :ref:`lib_dfu_target` library to manage the DFU process, providing a single interface to support different types of firmware upgrades. +Currently, the following types of firmware upgrades are supported: + +* MCUboot-style upgrades (:c:macro:`LWM2M_OS_DFU_IMG_TYPE_APPLICATION`) +* Modem delta upgrades (:c:macro:`LWM2M_OS_DFU_IMG_TYPE_MODEM_DELTA`) + +The type of upgrade is determined when the library calls the :c:func:`lwm2m_os_dfu_img_type` function in the abstraction layer upon receiving a new firmware image. + +If MCUboot-style upgrades are enabled, the LwM2M carrier library uses the function :c:func:`lwm2m_os_dfu_application_update_validate` to validate the application image update. +A ``__weak`` implementation of the function is included, which checks if the currently running image is not yet confirmed as valid (which is the case after an upgrade) and marks it appropriately. diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/msc.rst b/doc/nrf/libraries/bin/lwm2m_carrier/msc.rst index 9787b638673..9f5dcaf623f 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/msc.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/msc.rst @@ -13,9 +13,9 @@ The following message sequence chart shows the states of the ``lwm2m_carrier_thr The following message sequence chart shows FOTA updates: .. figure:: /libraries/bin/lwm2m_carrier/images/lwm2m_carrier_msc_fota_success.svg - :alt: LwM2M server initiated FOTA + :alt: LwM2M Server initiated FOTA - LwM2M server initiated FOTA + LwM2M Server initiated FOTA The following message sequence chart shows that FOTA fails at run time if an invalid CA certificate is provided: diff --git a/doc/nrf/libraries/bin/lwm2m_carrier/requirements.rst b/doc/nrf/libraries/bin/lwm2m_carrier/requirements.rst index c393260cb53..b6e137e41bd 100644 --- a/doc/nrf/libraries/bin/lwm2m_carrier/requirements.rst +++ b/doc/nrf/libraries/bin/lwm2m_carrier/requirements.rst @@ -15,7 +15,6 @@ Following are some of the requirements and limitations of the application while * Packet Domain events (``AT+CGEREP``). * Extended signal quality events (``AT%CESQ``). * ODIS events (``AT+ODISNTF``). - * Universal Integrated Circuit Card events (``AT%XSIM``). * Network Time events (``AT%XTIME``). * Modem Domain events (``AT%MDMEV``). * Report Network Error Codes events (``AT+CNEC``) - EPS Session Management events are used by the LwM2M carrier library. @@ -40,10 +39,17 @@ Following are some of the requirements and limitations of the application while * The socket is released by the library again upon the next reboot, or in the event of a FOTA error. * If the application always needs a TLS socket, it can use `Mbed TLS`_. -* The LwM2M carrier library uses both the DTLS sessions made available through the modem. Therefore, the application cannot run any DTLS sessions. +* When in the Verizon network, the LwM2M carrier library uses both the DTLS sessions made available through the modem. + Therefore, the application cannot run any DTLS or TLS sessions. + + * In other networks, the application can still use one DTLS session and one TLS session (or two DTLS sessions). + * For more information, see the :c:macro:`LWM2M_CARRIER_EVENT_FOTA_START` event in :ref:`lwm2m_events`. * The LwM2M carrier library provisions the necessary security credentials to the security tags 25, 26, 27, 28. These tags must not be used by the application. +* If the Kconfig option :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_SEC_TAG` is set, the range follows that ``sec_tag`` instead. + + * For example, setting :kconfig:option:`CONFIG_LWM2M_CARRIER_SERVER_SEC_TAG` to 42 uses the security tag range 43 to 46 instead of 25 to 28. * The CA certificates that are used for out-of-band FOTA must be provided by the application. Out-of-band FOTA updates are done by the :ref:`lib_download_client`. diff --git a/doc/nrf/libraries/bluetooth_services/mesh.rst b/doc/nrf/libraries/bluetooth_services/mesh.rst index f3628881496..5754afd6ba5 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh.rst @@ -3,7 +3,7 @@ Bluetooth Mesh profile ###################### -Bluetooth® mesh is supported for development in |NCS|, through the Zephyr :ref:`zephyr:bluetooth_mesh` implementation. +Bluetooth® Mesh is supported for development in |NCS|, through the Zephyr :ref:`zephyr:bluetooth_mesh` implementation. Nordic Semiconductor's implementation of the Bluetooth Mesh allows applications to use the features provided by the Bluetooth Mesh when running on supported Nordic devices. The `Bluetooth Mesh profile specification`_ is developed and published by the Bluetooth® Special Interest Group (SIG). diff --git a/doc/nrf/libraries/bluetooth_services/mesh/dk_prov.rst b/doc/nrf/libraries/bluetooth_services/mesh/dk_prov.rst index 518c28e2869..34e38e70bac 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/dk_prov.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/dk_prov.rst @@ -9,7 +9,7 @@ Bluetooth Mesh provisioning handler for Nordic DKs This application-side module is a basic implementation of the provisioning process handling for Development Kits from Nordic Semiconductor. It supports four types of out-of-band (OOB) authentication methods and uses the Hardware Information driver to generate a deterministic UUID to uniquely represent the device. -For more information about provisioning in Bluetooth® mesh, see the :ref:`zephyr:bluetooth_mesh_provisioning` page in Zephyr. +For more information about provisioning in Bluetooth® Mesh, see the :ref:`zephyr:bluetooth_mesh_provisioning` page in Zephyr. Used primarily in :ref:`bt_mesh_samples` applications, this handler acts as a reference implementation for the application-specific part of provisioning. It is enabled with the :kconfig:option:`CONFIG_BT_MESH_DK_PROV` option and by calling :c:func:`bt_mesh_dk_prov_init` in main. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/gen_prop_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/gen_prop_srv.rst index c519dae00ce..30b9e62203a 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/gen_prop_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/gen_prop_srv.rst @@ -52,7 +52,7 @@ Extended models Generic Admin Property Server and Generic Manufacturer Property Server should both extend the Generic User Property Server. This is not handled automatically by the model implementation. -For this reason, to ensure compliance with the Bluetooth® mesh model specification, a Generic User Property Server must be instantiated in the same element in the device composition data as the Generic Admin or Generic Manufacturer Property Server. +For this reason, to ensure compliance with the Bluetooth® Mesh model specification, a Generic User Property Server must be instantiated in the same element in the device composition data as the Generic Admin or Generic Manufacturer Property Server. Persistent storage ================== diff --git a/doc/nrf/libraries/bluetooth_services/mesh/light_ctl_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/light_ctl_srv.rst index ec522bb910f..f84aca3f2d4 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/light_ctl_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/light_ctl_srv.rst @@ -51,7 +51,7 @@ The Lightness and Light Temperature Server callbacks will pass pointers to :c:me .. note:: The Light CTL Server will verify that its internal Light Temperature Server is instantiated on a subsequent element on startup. - If the Light Temperature Server is missing or instantiated on the same or a preceding element, the Bluetooth® mesh startup procedure will fail, and the device will not be responsive. + If the Light Temperature Server is missing or instantiated on the same or a preceding element, the Bluetooth® Mesh startup procedure will fail, and the device will not be responsive. States ====== diff --git a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_cli.rst b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_cli.rst index 6fa778c5894..a7489938228 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_cli.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_cli.rst @@ -7,6 +7,13 @@ Light Lightness Control Client :local: :depth: 2 +.. note:: + This model interacts with the new sensor API introduced as of |NCS| v2.6.0. + As a consequence, parts of the model API have been changed as well. + The old API is deprecated, but still available by enabling the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE`. + The Kconfig option is enabled by default in the deprecation period. + See the documentation for |NCS| versions prior to v2.6.0 for documentation about the old sensor API. + The Light Lightness Control (LC) Client configures and interacts with the :ref:`bt_mesh_light_ctrl_srv_readme`. The Light LC Client creates a single model instance in the mesh composition data, and it can send messages to both the Light LC Server and the Light LC Setup Server, as long as it has the right application keys. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_reg_spec.rst b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_reg_spec.rst index e4e68046aa5..f1c0e28c422 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_reg_spec.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_reg_spec.rst @@ -3,7 +3,7 @@ Specification-defined illuminance regulator ########################################### -This module implements the illuminance regulator defined in the Bluetooth® mesh model specification. +This module implements the illuminance regulator defined in the Bluetooth® Mesh model specification. The regulator operates in a compile time configurable update interval between 10 and 100 ms. The interval can be configured through the :kconfig:option:`CONFIG_BT_MESH_LIGHT_CTRL_REG_SPEC_INTERVAL` option. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_srv.rst index ddbbf55405a..b69de777d26 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/light_ctrl_srv.rst @@ -7,12 +7,19 @@ Light Lightness Control Server :local: :depth: 2 +.. note:: + This model interacts with the new sensor API introduced as of |NCS| v2.6.0. + As a consequence, parts of the model API have been changed as well. + The old API is deprecated, but still available by enabling the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE`. + The Kconfig option is enabled by default in the deprecation period. + See the documentation for |NCS| versions prior to v2.6.0 for documentation about the old sensor API. + The Light Lightness Control (LC) Server controls a single :ref:`bt_mesh_lightness_srv_readme` instance on the same device with a state machine. The state machine defines common behavior for a light fixture through three states, each with its own timing parameters and light levels. As input to its state machine, the Light LC Server listens for Sensor and OnOff messages. -In addition to the state machine, the Light LC Server may optionally use a regulator to control the ambient illuminance in the room. +In addition to the state machine, the Light LC Server may optionally use a regulator to control the ambient illuminance in the environment. The regulator requires illuminance sensor readings acting as feedback for its regulator loop. The Lightness Control Server is always disabled by default, and must be enabled by a :ref:`bt_mesh_light_ctrl_cli_readme`. @@ -79,10 +86,10 @@ Lightness state machine The Light LC Server's lightness state machine operates in the following states: Standby - There is no activity in the room, and the device's light are either off or dimmed. + There is no activity in the environment, and the lights are either off or dimmed. On - There is activity in the room, and the lights are on. + There is activity in the environment, and the lights are on. Prolong There is no activity detected. @@ -105,14 +112,17 @@ Timeout The state machine automatically moves into the next state. On - Toggled when a motion sensor is triggered or the On button is pressed on a light switch. + Toggled when the On button is pressed on a light switch. + +Occupancy On + Toggled when a motion sensor is triggered. Off Toggled when the Off button is pressed on a light switch. The On and Prolong states will start a timer as soon as the transition into the state is finished. When this timer expires, the state machine will automatically go into the next state. -If the On event is triggered while in the On state, the timer is reset, and the transition to the Prolong state is postponed. +If the On or Occupancy On event is triggered while in the On state, the timer is reset, and the transition to the Prolong state is postponed. .. figure:: images/bt_mesh_light_ctrl_states.svg :alt: Light Lightness Control Server state machine @@ -132,7 +142,7 @@ To avoid having a Light Lightness Server running independently forever, the Ligh The resume timer can be configured with the :kconfig:option:`CONFIG_BT_MESH_LIGHT_CTRL_SRV_RESUME_DELAY` option, and is disabled by default. .. note:: - The resume timer does not exist in the Bluetooth® mesh specification, and may become incompatible with future specification changes. + The resume timer does not exist in the Bluetooth® Mesh specification, and may become incompatible with future specification changes. Although it does not break the specification or qualification tests in the current iteration of the Bluetooth Mesh specification, its behavior may be unexpected for third party devices, and should be used with caution. State machine outputs @@ -157,44 +167,50 @@ Target illuminance level External event triggers ----------------------- -While the Timeout event is controlled internally, the On and Off events are produced by external behavior. +While the Timeout event is controlled internally, the On, Occupancy On and Off events are produced by external behavior. On event ~~~~~~~~ -The On event lets the Light LC Server know that there is activity in the room. -It can be generated by light switches and sensors. +The On event can be generated by light switches. +Light switches can implement one of the following models to send On messages that turn the Light LC Server on: -* Light switches can implement one of the following models to send On messages that turn the Light LC Server on: +* The :ref:`bt_mesh_onoff_cli_readme` model, which should publish to the Light LC Server's extended Generic OnOff Server model. +* The :ref:`bt_mesh_light_ctrl_cli_readme` model, which should publish Light OnOff Set messages to the Light LC Server. - * The :ref:`bt_mesh_onoff_cli_readme` model -- which should publish to the Light LC Server's extended Generic OnOff Server model. - * The :ref:`bt_mesh_light_ctrl_cli_readme` model -- which should publish Light OnOff Set messages to the Light LC Server. +.. _bt_mesh_light_ctrl_srv_occupancy_on_event: -* Occupancy sensors can also trigger the On event, depending on the current state and occupancy mode: +Occupancy On event +~~~~~~~~~~~~~~~~~~ - * If the occupancy mode is enabled, sensor readings that indicate activity can trigger an On event at any time. - * If the occupancy mode is disabled, sensors cannot turn the lights on, but they will still prevent lights from turning off. +The Occupancy On event lets the Light LC Server know that there is activity in the sensor's proximity. +It can be generated by sensors. -The following sensor types can also trigger the On event: +Occupancy sensors can trigger the Occupancy On event, depending on the current state and occupancy mode: + +* If the occupancy mode is enabled, sensor readings that indicate activity can trigger an Occupancy On event at any time. +* If the occupancy mode is disabled, sensors cannot turn the lights on, but they will still prevent lights from turning off. + +The following sensor types can also trigger the Occupancy On event: Motion sensed - :c:var:`bt_mesh_sensor_motion_sensed` - Any sensor value higher than 0 triggers an On event in the Light LC Server state machine. - Messages with a value of 0 are ignored. + Any sensor value higher than ``0`` triggers an Occupancy On event in the Light LC Server state machine. + Messages with a value of ``0`` are ignored. People count - :c:var:`bt_mesh_sensor_people_count` - Any sensor value higher than ``0`` triggers an On event in the Light LC Server state machine. + Any sensor value higher than ``0`` triggers an Occupancy On event in the Light LC Server state machine. Messages with a value of ``0`` are ignored. Presence detected - :c:var:`bt_mesh_sensor_presence_detected` - Messages with a ``true`` value triggers an On event in the Light LC Server state machine. + Messages with a ``true`` value triggers an Occupancy On event in the Light LC Server state machine. Messages with a ``false`` value are ignored. Time since motion sensed - :c:var:`bt_mesh_sensor_time_since_motion_sensed` - When the sensor's *Time since motion sensed* value is lower than the Light LC Server's occupancy delay, the Light LC Server starts a timer that expires at the time equal to *Motion sensed* plus *occupancy delay*. - When this timer expires, an On event is generated. + When the sensor's :c:var:`bt_mesh_sensor_time_since_motion_sensed` value is lower than the Light LC Server's occupancy delay, the Light LC Server starts a timer that expires at the time equal to motion sensed plus occupancy delay. + When this timer expires, an Occupancy On event is generated. .. note:: - Only sensors reporting the *Time since motion sensed* type will be affected by the occupancy delay. + Only sensors reporting the :c:var:`bt_mesh_sensor_time_since_motion_sensed` sensor type will be affected by the occupancy delay. Other sensor triggers are always instantaneous. Off event diff --git a/doc/nrf/libraries/bluetooth_services/mesh/light_hsl.rst b/doc/nrf/libraries/bluetooth_services/mesh/light_hsl.rst index 654561f70cd..0094b16e4a6 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/light_hsl.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/light_hsl.rst @@ -13,7 +13,7 @@ While easy to visualize and explain to end users, the HSL does not map well to c The HSL models are best suited for applications where the color of the light is a primary function, such as decorative lighting. For applications where illumination is the primary function of the light, and its color and temperature is secondary, the CTL and xyL models might be better alternatives. -However, neither the Bluetooth® mesh model specification nor the |NCS| put any restrictions on the application areas for the different models. +However, neither the Bluetooth® Mesh model specification nor the |NCS| put any restrictions on the application areas for the different models. Developers may freely use the model best suited for their application. On the light fixture side, the HSL Server models are separated into three independent models: diff --git a/doc/nrf/libraries/bluetooth_services/mesh/model_types.rst b/doc/nrf/libraries/bluetooth_services/mesh/model_types.rst index d95db130523..8b17e116ad3 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/model_types.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/model_types.rst @@ -7,7 +7,7 @@ Bluetooth Mesh models overview :local: :depth: 2 -A Bluetooth® mesh model is a standardized component that defines a series of states and related behaviors. +A Bluetooth® Mesh model is a standardized component that defines a series of states and related behaviors. Models encapsulate a single feature of a mesh node, and expose this feature to the mesh network. Each mesh-based product implements several models. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/sensor.rst b/doc/nrf/libraries/bluetooth_services/mesh/sensor.rst index 0d1003e07b4..57664e78cf2 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/sensor.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/sensor.rst @@ -7,7 +7,13 @@ Bluetooth Mesh sensors :local: :depth: 2 -The Bluetooth® mesh specification provides a common scheme for representing all sensors. +.. note:: + A new sensor API is introduced as of |NCS| v2.6.0. + The old API is deprecated, but still available by enabling the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE`. + The Kconfig option is enabled by default in the deprecation period. + See the documentation for |NCS| versions prior to v2.6.0 for documentation about the old sensor API. + +The Bluetooth® Mesh specification provides a common scheme for representing all sensors. A single Bluetooth Mesh sensor instance represents a single physical sensor, and a mesh device may present any number of sensors to the network through a Sensor Server model. Sensors represent their measurements as a list of sensor channels, as described by the sensor's assigned type. @@ -18,6 +24,10 @@ Sensors are accessed through the Sensor models, which are documented separately: - :ref:`bt_mesh_sensor_srv_readme` - :ref:`bt_mesh_sensor_cli_readme` +.. note:: + Several floating point computations are done internally in the stack when using the sensor API. + It is recommended to enable the :kconfig:option:`CONFIG_FPU` Kconfig option to improve the performance of these computations. + .. _bt_mesh_sensor_basic_example: Basic example @@ -31,10 +41,17 @@ A sensor reporting the device operating temperature could combine the Bluetooth static int temp_get(struct bt_mesh_sensor *sensor, struct bt_mesh_msg_ctx *ctx, - struct sensor_value *rsp) + struct bt_mesh_sensor_value *rsp) { + struct sensor_value value; + int err; + sensor_sample_fetch(dev); - return sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, rsp); + err = sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &value); + if (err) { + return err; + } + return bt_mesh_sensor_value_from_sensor_value(&value, rsp); } struct bt_mesh_sensor temp_sensor = { @@ -50,6 +67,20 @@ A sensor reporting the device operating temperature could combine the Bluetooth Additionally, a pointer to the ``temp_sensor`` structure should be passed to a Sensor Server to be exposed to the mesh. See :ref:`bt_mesh_sensor_srv_readme` for details. +.. _bt_mesh_sensor_values: + +Sensor values +************* + +Sensor values are represented in the API using :c:struct:`bt_mesh_sensor_value`. +This contains the raw sensor value, encoded according to a certain Bluetooth GATT Characteristic, and a pointer to :c:struct:`bt_mesh_sensor_format` describing how that characteristic is encoded/decoded. + +Applications will normally not access :c:member:`bt_mesh_sensor_value.raw` or the members of :c:member:`bt_mesh_sensor_value.format` directly. +Instead, API functions for converting between :c:struct:`bt_mesh_sensor_value` and the values suitable for application use are used. +An exception to this is when statically initializing :c:struct:`bt_mesh_sensor_value` at compile-time, in which case the API functions cannot be used. + +The sensor API is built to integrate well with the Zephyr :ref:`zephyr:sensor_api` API, and provides functions for converting to and from :c:struct:`sensor_value`. + .. _bt_mesh_sensor_types: Sensor types @@ -60,14 +91,11 @@ Each sensor type is assigned its own Device Property ID, as specified in the Blu Like the Device Properties, the Sensor types are connected to a Bluetooth GATT Characteristic, which describes the unit, range, resolution and encoding scheme of the sensor type. .. note:: - The Bluetooth® mesh specification only allows sensor types that have a Device Property ID in the Bluetooth Mesh device properties specification. + The Bluetooth Mesh specification only allows sensor types that have a Device Property ID in the Bluetooth Mesh device properties specification. It's not possible to represent vendor specific sensor values. The sensor types may either be used as the data types of the sensor output values, or as configuration parameters for the sensors. -The Bluetooth Mesh Sensor type API is built to mirror and integrate well with the Zephyr :ref:`zephyr:sensor_api` API. -Some concepts in the Bluetooth Mesh specification are changed slightly to fit better with the Zephyr Sensor API, with focus on making integration as simple as possible. - .. _bt_mesh_sensor_types_channels: Sensor channels @@ -77,9 +105,8 @@ Each sensor type may consist of one or more channels. The list of sensor channels in each sensor type is immutable, and all channels must always have a valid value when the sensor data is passed around. This is slightly different from the sensor type representation in the Bluetooth Mesh specification, which represents multi-channel sensors as structures, rather than flat lists. -Each channel in a sensor type is represented by a single :c:struct:`sensor_value`. -For sensor values that are represented as whole numbers, the fractional part of the value (:c:member:`sensor_value.val2`) is ignored. -Boolean types are inferred only from the integer part of the value (:c:member:`sensor_value.val1`). +Each channel in a sensor type is represented by a single :c:struct:`bt_mesh_sensor_value` structure. +This contains the raw value of the sensor value, and a pointer to :c:struct:`bt_mesh_sensor_format` used for encoding and decoding of the raw value. Every sensor channel has a name and a unit, as listed in the sensor type documentation. The name and unit are only available if :kconfig:option:`CONFIG_BT_MESH_SENSOR_LABELS` option is set, and can aid in debugging and presentation of the sensor output. @@ -92,11 +119,12 @@ Before encoding, the sensor values are rounded to their nearest available repres .. code-block:: c + struct bt_mesh_sensor_value sensor_val; + /* Sensor value: 7.3123 A */ - struct sensor_value electrical_current = { - .val1 = 7, - .val2 = 312300, /* 6 digit fraction */ - }; + (void)bt_mesh_sensor_value_from_float( + &bt_mesh_sensor_format_electric_current, + 7.3123f, &sensor_val); Various other encoding schemes are used to represent non-scalars. See the documentation or specification for the individual sensor channels for more details. @@ -219,8 +247,8 @@ If the sensor has a descriptor, a pointer to it should be passed to :c:member:`b static const struct bt_mesh_sensor_descriptor temp_sensor_descriptor = { .tolerance = { - .negative = { .val1 = 0, .val2 = 750000 }, - .positive = { .val1 = 3, .val2 = 500000 }, + .negative = BT_MESH_SENSOR_TOLERANCE_ENCODE(0.75f) + .positive = BT_MESH_SENSOR_TOLERANCE_ENCODE(3.5f) }, .sampling_type = BT_MESH_SENSOR_SAMPLING_ARITHMETIC_MEAN, .period = 300, @@ -250,7 +278,20 @@ Sensor data =========== Sensor data is accessed through the :c:member:`bt_mesh_sensor.get` callback, which is expected to fill the ``rsp`` parameter with the most recent sensor data and return a status code. -Each sensor channel will be encoded internally according to the sensor type. +Each sensor channel must be encoded according to the channel format. +This can be done using one of the conversion functions :c:func:`bt_mesh_sensor_value_from_micro`, :c:func:`bt_mesh_sensor_value_from_float` or :c:func:`bt_mesh_sensor_value_from_sensor_value`. +A pointer to the format for a given channel can be found through the :c:struct:`bt_mesh_sensor` pointer passed to the callback in a following way: + +.. code-block:: c + + static int get_cb(struct bt_mesh_sensor *sensor, + struct bt_mesh_msg_ctx *ctx, + struct bt_mesh_sensor_value *rsp) + { + /* Get the correct format to use for encoding rsp[0]: */ + const struct_bt_mesh_sensor_format *channel_0_format = + sensor->type->channels[0].format; + } The sensor data in the callback typically comes from a sensor using the :ref:`Zephyr sensor API `. The Zephyr sensor API records samples in two steps: @@ -286,12 +327,27 @@ Example: A three-channel sensor (average ambient temperature in a period of day) .. code-block:: c + /* Macro for statically initializing time_decihour_8. + * Raw is computed by multiplying by 10 according to + * the resolution specified in the GATT Specification + * Supplement. + */ + #define TIME_DECIHOUR_8_INIT(_hours) { \ + .format = &bt_mesh_sensor_format_time_decihour_8, \ + .raw = { (_hours) * 10 } \ + } + + #define COLUMN_INIT(_start, _width) { \ + TIME_DECIHOUR_8_INIT(_start), \ + TIME_DECIHOUR_8_INIT(_width) \ + } + /* 4 columns representing different hours in a day */ static const struct bt_mesh_sensor_column columns[] = { - {{0}, {6}}, - {{6}, {12}}, - {{12}, {18}}, - {{18}, {24}}, + COLUMN_INIT(0, 6), + COLUMN_INIT(6, 6), + COLUMN_INIT(12, 6), + COLUMN_INIT(18, 6) }; static struct bt_mesh_sensor temp_sensor = { @@ -304,16 +360,34 @@ Example: A three-channel sensor (average ambient temperature in a period of day) }; /** Sensor data is divided into columns and filled elsewhere */ - static struct sensor_value avg_temp[ARRAY_SIZE(columns)]; + static float avg_temp[ARRAY_SIZE(columns)]; static int getter(struct bt_mesh_sensor *sensor, struct bt_mesh_msg_ctx *ctx, - uint32_t column_index, struct sensor_value *value) + uint32_t column_index, struct bt_mesh_sensor_value *value) { - value[0] = avg_temp[column_index]; + int err = bt_mesh_sensor_value_from_float( + sensor->type->channels[0].format, &avg_temp[column_index], &value[0]); + + if (err) { + return err; + } value[1] = columns[column_index].start; - value[2] = columns[column_index].end; - return 0; + /* Compute end value from column start and width: */ + int64_t start, width; + enum bt_mesh_sensor_value_status status; + + status = bt_mesh_sensor_value_to_micro(&columns[column_index].start, &start); + if (!bt_mesh_sensor_status_is_numeric(status)) { + return -EINVAL; + } + status = bt_mesh_sensor_value_to_micro(&columns[column_index].width, &width); + if (!bt_mesh_sensor_value_status_is_numeric(status)) { + return -EINVAL; + } + return bt_mesh_sensor_value_from_micro( + bt_mesh_sensor_column_format_get(sensor), + start + width, &value[2]); } Example: Single-channel sensor (motion sensed) as a sensor series: @@ -332,14 +406,14 @@ Example: Single-channel sensor (motion sensed) as a sensor series: }; /** Sensor data is divided into columns and filled elsewhere */ - static struct sensor_value motion[COLUMN_COUNT]; + static uint8_t motion[COLUMN_COUNT]; static int getter(struct bt_mesh_sensor *sensor, struct bt_mesh_msg_ctx *ctx, - uint32_t column_index, struct sensor_value *value) + uint32_t column_index, struct bt_mesh_sensor_value *value) { - value[0] = motion[column_index]; - - return 0; + return bt_mesh_sensor_value_from_micro( + sensor->type->channels[0].format, + motion[column_index] * 1000000LL, &value[0]); } Sensor settings @@ -360,7 +434,7 @@ The following code is an example of adding a setting to a sensor: struct bt_mesh_sensor *sensor, const struct bt_mesh_sensor_setting *setting, struct bt_mesh_msg_ctx *ctx, - struct sensor_value *rsp) + struct bt_mesh_sensor_value *rsp) { /** Get the current threshold in an application defined way and * store it in rsp. @@ -372,7 +446,7 @@ The following code is an example of adding a setting to a sensor: struct bt_mesh_sensor *sensor, const struct bt_mesh_sensor_setting *setting, struct bt_mesh_msg_ctx *ctx, - const struct sensor_value *value) + const struct bt_mesh_sensor_value *value) { /** Store incoming threshold in application-defined way. * Return error code to reject set. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/sensor_cli.rst b/doc/nrf/libraries/bluetooth_services/mesh/sensor_cli.rst index f6dfae806a2..5fdedc42855 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/sensor_cli.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/sensor_cli.rst @@ -7,6 +7,12 @@ Sensor Client :local: :depth: 2 +.. note:: + A new sensor API is introduced as of |NCS| v2.6.0. + The old API is deprecated, but still available by enabling the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE`. + The Kconfig option is enabled by default in the deprecation period. + See the documentation for |NCS| versions prior to v2.6.0 for documentation about the old sensor API. + The Sensor Client model reads and configures the sensors exposed by :ref:`bt_mesh_sensor_srv_readme` models. Unlike the Sensor Server model, the Sensor Client only creates a single model instance in the mesh composition data. @@ -144,7 +150,7 @@ mesh models sensor series-entry get Get the value of a column for a sensor on the server. * ``SensorID`` - Selects the sensor for which to get the entry value. - * ``Column`` - Start value of the column for which to get the entry value. + * ``Column`` - For sensors with three channels: Start value of the column for which to get the entry value. For other sensors: Index of the column for which to get the entry value. mesh models sensor series-entries-get [ ] diff --git a/doc/nrf/libraries/bluetooth_services/mesh/sensor_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/sensor_srv.rst index 3aa0d420f0b..0462e6c2b72 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/sensor_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/sensor_srv.rst @@ -7,6 +7,12 @@ Sensor Server :local: :depth: 2 +.. note:: + A new sensor API is introduced as of |NCS| v2.6.0. + The old API is deprecated, but still available by enabling the Kconfig option :kconfig:option:`CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE`. + The Kconfig option is enabled by default in the deprecation period. + See the documentation for |NCS| versions prior to v2.6.0 for documentation about the old sensor API. + The Sensor Server model holds a list of sensors, and exposes them to the mesh network. There may be multiple Sensor Server models on a single mesh node, and each model may hold up to 47 sensors. @@ -64,6 +70,8 @@ Extended models None. +.. _bt_mesh_sensor_srv_persistent_readme: + Persistent storage ================== diff --git a/doc/nrf/libraries/bluetooth_services/mesh/sensor_types.rst b/doc/nrf/libraries/bluetooth_services/mesh/sensor_types.rst index 3e339838f67..bbabb0a8f46 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/sensor_types.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/sensor_types.rst @@ -1,13 +1,13 @@ .. _bt_mesh_sensor_types_readme: -Bluetooth Mesh sensor types -########################### +Bluetooth Mesh sensor formats and sensor types +############################################## .. contents:: :local: :depth: 2 -All sensor types are collected in :file:`include/bluetooth/mesh/sensor_types.h`, and are divided into the categories listed in the page index. +All sensor formats and sensor types are collected in the :file:`include/bluetooth/mesh/sensor_types.h` file, and are divided into the categories listed in the page index. To keep the total flash usage down, the sensor types are only instantiated if they're referenced by the application. This behavior can be overridden by enabling :kconfig:option:`CONFIG_BT_MESH_SENSOR_ALL_TYPES`. @@ -17,16 +17,86 @@ Sensor types can be forced into the build by the :c:macro:`BT_MESH_SENSOR_TYPE_F Sensor types may only be declared in the ``bt_mesh_sensor_types`` static linker section. -See :ref:`bt_mesh_sensor_types` for information on how to use these sensor types when initializing and using sensors. +See :ref:`bt_mesh_sensor_types` for information on how to use these sensor types and formats when initializing and using sensors. .. doxygengroup:: bt_mesh_sensor_types :project: nrf :content-only: +.. _bt_mesh_sensor_types_formats_readme: + +Sensor formats +************** + +.. _bt_mesh_sensor_formats_percentage_readme: + +Percentage sensor formats +========================= + +.. doxygengroup:: bt_mesh_sensor_formats_percentage + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_formats_environmental_readme: + +Environmental sensor formats +============================ + +.. doxygengroup:: bt_mesh_sensor_formats_environmental + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_formats_time_readme: + +Time sensor formats +=================== + +.. doxygengroup:: bt_mesh_sensor_formats_time + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_formats_electrical_readme: + +Electrical sensor formats +========================= + +.. doxygengroup:: bt_mesh_sensor_formats_electrical + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_formats_lighting_readme: + +Lighting sensor formats +======================= + +.. doxygengroup:: bt_mesh_sensor_formats_lighting + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_formats_miscellaneous_readme: + +Miscellaneous sensor formats +============================ + +.. doxygengroup:: bt_mesh_sensor_formats_miscellaneous + :project: nrf + :members: + :content-only: + +.. _bt_mesh_sensor_types_types_readme: + +Sensor types +************ + .. _bt_mesh_sensor_types_occupancy_readme: Occupancy sensor types -********************** +====================== .. doxygengroup:: bt_mesh_sensor_types_occupancy :project: nrf @@ -36,7 +106,7 @@ Occupancy sensor types .. _bt_mesh_sensor_types_ambient_temperature_readme: Ambient temperature sensor types -******************************** +================================ .. doxygengroup:: bt_mesh_sensor_types_ambient_temperature :project: nrf @@ -46,7 +116,7 @@ Ambient temperature sensor types .. _bt_mesh_sensor_types_environmental_readme: Environmental sensor types -************************** +========================== .. doxygengroup:: bt_mesh_sensor_types_environmental :project: nrf @@ -56,7 +126,7 @@ Environmental sensor types .. _bt_mesh_sensor_types_device_operating_temperature_readme: Device operating temperature sensor types -***************************************** +========================================= .. doxygengroup:: bt_mesh_sensor_types_device_operating_temperature :project: nrf @@ -66,7 +136,7 @@ Device operating temperature sensor types .. _bt_mesh_sensor_types_electrical_input_readme: Electrical input sensor types -***************************** +============================= .. doxygengroup:: bt_mesh_sensor_types_electrical_input :project: nrf @@ -76,7 +146,7 @@ Electrical input sensor types .. _bt_mesh_sensor_types_energy_management_readme: Energy management sensor types -****************************** +============================== .. doxygengroup:: bt_mesh_sensor_types_energy_management :project: nrf @@ -86,7 +156,7 @@ Energy management sensor types .. _bt_mesh_sensor_types_photometry_readme: Photometry sensor types -*********************** +======================= .. doxygengroup:: bt_mesh_sensor_types_photometry :project: nrf @@ -96,7 +166,7 @@ Photometry sensor types .. _bt_mesh_sensor_types_power_supply_output_readme: Power supply output sensor types -******************************** +================================ .. doxygengroup:: bt_mesh_sensor_types_power_supply_output :project: nrf @@ -106,7 +176,7 @@ Power supply output sensor types .. _bt_mesh_sensor_types_warranty_and_service_readme: Warranty and Service sensor types -********************************* +================================= .. doxygengroup:: bt_mesh_sensor_types_warranty_and_service :project: nrf diff --git a/doc/nrf/libraries/bluetooth_services/mesh/time_tai.rst b/doc/nrf/libraries/bluetooth_services/mesh/time_tai.rst index 2e6efb4ec01..56055bcf89d 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/time_tai.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/time_tai.rst @@ -18,5 +18,5 @@ This allows applications to calculate the number of seconds between any two TAI To convert to UTC, TAI based applications keep track of the UTC leap seconds separately, as well as the time zone and time zone adjustments. -The Bluetooth® mesh Time models share time as a composite state of TAI seconds, 256 subseconds, UTC offset, time zone steps and uncertainty. +The Bluetooth® Mesh Time models share time as a composite state of TAI seconds, 256 subseconds, UTC offset, time zone steps and uncertainty. See :cpp:type:`bt_mesh_time_status` for details. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm.rst b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm.rst index f6d5ec18493..55f2167de5a 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm.rst @@ -7,7 +7,7 @@ Distance Measurement models :local: :depth: 2 -The Distance Measurement vendor models allow users to measure distance between different Bluetooth® mesh devices. +The Distance Measurement vendor models allow users to measure distance between different Bluetooth® Mesh devices. The Distance Measurement models also feature their own common types, listed below. For types common to all models, see :ref:`bt_mesh_models`. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_cli.rst b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_cli.rst index fd609eab39f..4729eb57a6d 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_cli.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_cli.rst @@ -27,7 +27,7 @@ None. Shell commands ************** -The Bluetooth® mesh shell subsystem provides a set of commands to interact with the Distance Measurement Client model instantiated on a device. +The Bluetooth® Mesh shell subsystem provides a set of commands to interact with the Distance Measurement Client model instantiated on a device. To make these commands available, enable the following Kconfig options: diff --git a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_srv.rst index b1e443df710..fc50e546c6c 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/vnd/dm_srv.rst @@ -7,7 +7,7 @@ Distance Measurement Server :local: :depth: 2 -The Distance Measurement Server vendor model provides capabilities to measure distance between Bluetooth® mesh devices within radio proximity. +The Distance Measurement Server vendor model provides capabilities to measure distance between Bluetooth® Mesh devices within radio proximity. The measurements are conducted through the :ref:`mod_dm` library. At creation, each Distance Measurement Server instance must be initialized with a memory object that can hold one or more measurement results. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/vnd/images/bt_mesh_le_pair_resp.svg b/doc/nrf/libraries/bluetooth_services/mesh/vnd/images/bt_mesh_le_pair_resp.svg new file mode 100644 index 00000000000..f02269c0389 --- /dev/null +++ b/doc/nrf/libraries/bluetooth_services/mesh/vnd/images/bt_mesh_le_pair_resp.svg @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + nRF Connect SDK diagram + + Sheet.1 + Max 800 px + + + Max 800 px + + Sheet.2 + Max 780 px + + + Max 780 px + + Sheet.3 + + + + Sheet.4 + + + + Straight Line + + + + Straight Line.15 + + + + Line Arrow + Passkey Reset + + + + + Passkey Reset + + Arced Line Double Arrow + + + + + + Box + bt_rand() + bt_passkey_set() + + bt_rand() + bt_passkey_set() + + Arced Line Double Arrow.30 + + + + + + Box.31 + Setting the received passkey + + Setting the received passkey + + Arced Line Double Arrow.32 + + + + + + Box.33 + bt_conn_auth_pairing_confirm() + + bt_conn_auth_pairing_confirm() + + Arced Line Double Arrow.38 + + + + + + Box.39 + bt_mesh_le_pair_resp_passkey_invalidate() + + bt_mesh_le_pair_resp_passkey_invalidate() + + Line Arrow.47 + Passkey Status (passkey) + + + + + Passkey Status (passkey) + + Signal, right-to-left + + Dynamic connector.32 + + + + Sheet.19 + bt_conn_auth_cb.pairing_display() + + bt_conn_auth_cb.pairing_display() + + + Signal, right-to-left.52 + + Dynamic connector.32 + + + + Sheet.22 + bt_conn_auth_cb.pairing_confirm() + + bt_conn_auth_cb.pairing_confirm() + + + Signal, right-to-left.55 + + Dynamic connector.32 + + + + Sheet.25 + bt_conn_auth_info_cb.pairing_complete() / bt_conn_auth_info_c... + + bt_conn_auth_info_cb.pairing_complete() / bt_conn_auth_info_cb.pairing_failed() + + + Signal, left-to-right + + Dynamic connector.31 + + + + Sheet.28 + A passkey is requested + + A passkey is requested + + + Nordic Lake + Initiator (Mobile app) + + Initiator (Mobile app) + + Nordic Lake.77 + LE Pairing Responder (Mesh node) + + LE Pairing Responder (Mesh node) + + Nordic Middle Grey + The Initiator is ready for pairing + + The Initiator is ready for pairing + + Nordic Middle Grey.82 + The Initiator requests the passkey + + The Initiator requests the passkey + + Nordic Middle Grey.84 + The Initiator initiates the pairing + + The Initiator initiates the pairing + + Nordic Middle Grey.86 + Pairing completed / failed + + Pairing completed / failed + + diff --git a/doc/nrf/libraries/bluetooth_services/mesh/vnd/le_pair_resp.rst b/doc/nrf/libraries/bluetooth_services/mesh/vnd/le_pair_resp.rst index a50fa8fabdc..287352d49ee 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/vnd/le_pair_resp.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/vnd/le_pair_resp.rst @@ -7,16 +7,28 @@ LE Pairing Responder :local: :depth: 2 -The LE Pairing Responder model can be used to hand over a passkey that will authenticate a Bluetooth LE connection over a mesh network when it is not possible to use other pairing methods. +The LE Pairing Responder model is a vendor model. +This model can be used to hand over a passkey that will authenticate a Bluetooth LE connection over a mesh network when it is not possible to use other pairing methods. Before the pairing is initiated, an initiator should send an LE Pairing message with Passkey Reset sub-opcode to set a new passkey for the next pairing request. The passkey returned in the LE Pairing message with the Passkey Status sub-opcode should be used for the next pairing. +The passkey is generated using the :c:func:`bt_rand` function and set to the host using the :c:func:`bt_passkey_set` function. +The latter requires the :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` option to be enabled. + +.. note:: + The warning generated by the :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` option should be disregarded as long as the application always invalidates the previously used passkey by calling the :c:func:`bt_mesh_le_pair_resp_passkey_invalidate` function regardless of the pairing result (see below). + This model requires an application to only enable the display capability for the LE pairing by setting the :c:member:`bt_conn_auth_cb.pairing_display` callback. After every pairing request, the application must invalidate the previously used passkey by calling the :c:func:`bt_mesh_le_pair_resp_passkey_invalidate` function. This function can be called from callbacks :c:member:`bt_conn_auth_info_cb.pairing_complete` and :c:member:`bt_conn_auth_info_cb.pairing_failed`. See the :file:`samples/bluetooth/mesh/common/smp_bt_auth.c` file for the reference. +.. figure:: images/bt_mesh_le_pair_resp.svg + :alt: Diagram of interaction between an Initiator and the LE Pairing Responder model + +The model supports only LE Secure Connection pairing and requires the :kconfig:option:`CONFIG_BT_SMP_SC_ONLY` to be enabled. + Messages ======== diff --git a/doc/nrf/libraries/bluetooth_services/rpc.rst b/doc/nrf/libraries/bluetooth_services/rpc.rst index fd6f1c57eb9..cd44e122ccb 100644 --- a/doc/nrf/libraries/bluetooth_services/rpc.rst +++ b/doc/nrf/libraries/bluetooth_services/rpc.rst @@ -79,7 +79,7 @@ Then, you can invoke build command like this: .. parsed-literal:: :class: highlight - west build -b *board* -- -DOVERLAY_CONFIG=my_overlay_file.conf + west build -b *board* -- -DEXTRA_CONF_FILE=my_overlay_file.conf .. _ble_rpc_api: diff --git a/doc/nrf/libraries/bluetooth_services/services/fast_pair.rst b/doc/nrf/libraries/bluetooth_services/services/fast_pair.rst index 73ebc6efef3..053416931d2 100644 --- a/doc/nrf/libraries/bluetooth_services/services/fast_pair.rst +++ b/doc/nrf/libraries/bluetooth_services/services/fast_pair.rst @@ -7,7 +7,7 @@ Google Fast Pair Service (GFPS) :local: :depth: 2 -The Google Fast Pair Service (Fast Pair for short) implements a Bluetooth® Low Energy (LE) GATT Service required when :ref:`ug_bt_fast_pair`. +The Google Fast Pair Service (Fast Pair for short) implements a Bluetooth® Low Energy (LE) GATT Service required for :ref:`ug_bt_fast_pair` with the |NCS|. Service UUID ************ @@ -23,7 +23,7 @@ The implementation in the |NCS| follows these requirements. The Fast Pair service also contains additional GATT characteristics under the following conditions: * The Additional Data GATT characteristic is enabled when an extension requires it. - Currently, only the Personalized Name extension (:kconfig:option:`CONFIG_BT_FAST_PAIR_EXT_PN`) requires this characteristic. + Currently, only the Personalized Name extension (:kconfig:option:`CONFIG_BT_FAST_PAIR_PN`) requires this characteristic. Configuration ************* @@ -35,7 +35,7 @@ The following Kconfig options are also available for this module: * :kconfig:option:`CONFIG_BT_FAST_PAIR_STORAGE_USER_RESET_ACTION` - The option enables user reset action that is executed together with the Fast Pair factory reset operation. See the :ref:`ug_bt_fast_pair_factory_reset_custom_user_reset_action` for more details. * :kconfig:option:`CONFIG_BT_FAST_PAIR_STORAGE_ACCOUNT_KEY_MAX` - The option configures maximum number of stored Account Keys. -* :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_TINYCRYPT`, :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_MBEDTLS`, and :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_OBERON` - These options are used to select the cryptographic backend for Fast Pair. +* :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_TINYCRYPT`, :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_MBEDTLS`, :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_OBERON`, and :kconfig:option:`CONFIG_BT_FAST_PAIR_CRYPTO_PSA` - These options are used to select the cryptographic backend for Fast Pair. The Oberon backend is used by default. The Mbed TLS backend uses Mbed TLS crypto APIs, which are now considered legacy APIs. * :kconfig:option:`CONFIG_BT_FAST_PAIR_PN` - The option enables the `Fast Pair Personalized Name extension`_. @@ -132,9 +132,19 @@ The pairing flow and the set of Bluetooth authentication callbacks in use depend API documentation ***************** -| Header file: :file:`include/bluetooth/services/fast_pair.h` +| Header file: :file:`include/bluetooth/services/fast_pair/fast_pair.h` | Source files: :file:`subsys/bluetooth/services/fast_pair` .. doxygengroup:: bt_fast_pair :project: nrf :members: + +Fast Pair UUID API +================== + +| Header file: :file:`include/bluetooth/services/fast_pair/uuid.h` +| Source files: :file:`subsys/bluetooth/services/fast_pair` + +.. doxygengroup:: bt_fast_pair_uuid + :project: nrf + :members: diff --git a/doc/nrf/libraries/caf/ble_adv.rst b/doc/nrf/libraries/caf/ble_adv.rst index 5e9134bf489..cc298b35527 100644 --- a/doc/nrf/libraries/caf/ble_adv.rst +++ b/doc/nrf/libraries/caf/ble_adv.rst @@ -19,6 +19,7 @@ The following Kconfig options are available for this module: * :kconfig:option:`CONFIG_CAF_BLE_ADV` * :kconfig:option:`CONFIG_CAF_BLE_ADV_PM_EVENTS` +* :kconfig:option:`CONFIG_CAF_BLE_ADV_POWER_DOWN_ON_DISCONNECTION_REASON_0X15` * :kconfig:option:`CONFIG_CAF_BLE_ADV_DIRECT_ADV` * :kconfig:option:`CONFIG_CAF_BLE_ADV_FAST_ADV` * :kconfig:option:`CONFIG_CAF_BLE_ADV_FAST_ADV_TIMEOUT` @@ -98,6 +99,17 @@ This is done to ensure that the user does not try to connect to the device that The :kconfig:option:`CONFIG_CAF_BLE_ADV_GRACE_PERIOD` is enabled by default if the Swift Pair advertising data provider is enabled in the configuration. +Force power down on bonded peer power off +----------------------------------------- + +You can use the :kconfig:option:`CONFIG_CAF_BLE_ADV_POWER_DOWN_ON_DISCONNECTION_REASON_0X15` Kconfig option to force power down when a bonded peer disconnects with reason ``0x15`` (Remote Device Terminated due to Power Off). +On a Bluetooth LE peer event (:c:struct:`ble_peer_event`) reporting :c:enumerator:`PEER_STATE_DISCONNECTED` (:c:member:`ble_peer_event.state`) with reason ``0x15`` (:c:member:`ble_peer_event.reason`), the module performs the following: + + * Instantly stops Bluetooth LE advertising (the module enters power down state). + * Submits a force power down event (:c:struct:`force_power_down_event`). + +You can use this feature to prevent a bonded peer from waking up until activity on the peripheral is detected. + Implementation details ********************** @@ -127,7 +139,7 @@ The Bluetooth LE bond module broadcasts information related to bond control usin The |ble_adv| reacts on :c:struct:`ble_peer_operation_event` related to the Bluetooth peer change or erase advertising. The module performs one of the following operations: -* If there is a peer connected over Bluetooth, the |ble_adv| triggers disconnection and submits a :c:struct:`ble_peer_event` with :c:member:`ble_peer_event.state` set to :c:enum:`PEER_STATE_DISCONNECTING` to let other application modules prepare for the planned disconnection. +* If there is a peer connected over Bluetooth, the |ble_adv| triggers disconnection and submits a :c:struct:`ble_peer_event` with :c:member:`ble_peer_event.state` set to :c:enumerator:`PEER_STATE_DISCONNECTING` to let other application modules prepare for the planned disconnection. * Otherwise, the Bluetooth advertising with the newly selected Bluetooth local identity is started. Avoiding connection requests from unbonded centrals when bonded diff --git a/doc/nrf/libraries/caf/ble_state.rst b/doc/nrf/libraries/caf/ble_state.rst index 8f4c2cf8c38..6b8dcae6902 100644 --- a/doc/nrf/libraries/caf/ble_state.rst +++ b/doc/nrf/libraries/caf/ble_state.rst @@ -54,22 +54,14 @@ Connection state change ======================= The module propagates information about the connection state changes using :c:struct:`ble_peer_event`. -In this event, :c:member:`ble_peer_event.id` is a pointer to the connection object and :c:member:`ble_peer_event.state` is the connection state. .. figure:: images/caf_ble_state_transitions.svg :alt: Bluetooth connection state handling in CAF Bluetooth connection state handling in CAF -The connection state can be set to one of the following values: - -* :c:enum:`PEER_STATE_CONNECTED` - Bluetooth stack successfully connected to the remote peer. -* :c:enum:`PEER_STATE_CONN_FAILED` - Bluetooth stack failed to connect the remote peer. -* :c:enum:`PEER_STATE_SECURED` - Bluetooth stack set the connection security to at least level 2 (that is, encryption and no authentication). -* :c:enum:`PEER_STATE_DISCONNECTED` - Bluetooth stack disconnected from the remote peer. - Other application modules can call :c:func:`bt_conn_disconnect` to disconnect the remote peer. -The application module can submit a :c:struct:`ble_peer_event` with :c:member:`ble_peer_event.state` set to :c:enum:`PEER_STATE_DISCONNECTING` to let other application modules prepare for the disconnection. +The application module can submit a :c:struct:`ble_peer_event` with :c:member:`ble_peer_event.state` set to :c:enumerator:`PEER_STATE_DISCONNECTING` to let other application modules prepare for the disconnection. Connection parameter change =========================== diff --git a/doc/nrf/libraries/caf/sensor_manager.rst b/doc/nrf/libraries/caf/sensor_manager.rst index 2a29e4c447e..4446ae89c9a 100644 --- a/doc/nrf/libraries/caf/sensor_manager.rst +++ b/doc/nrf/libraries/caf/sensor_manager.rst @@ -31,7 +31,7 @@ The following Kconfig options are also available for the module: To use the module, you must complete the following requirements: 1. Physically connect the sensor. -#. Add and enable the sensor in the Devicetree file. +#. Add and enable the sensor in the devicetree file. For example, in the :file:`BOARD.dts` file. For more information about adding sensor device to devicetree, refer to :ref:`zephyr:use-dt-overlays`. #. Enable the :kconfig:option:`CONFIG_CAF_SENSOR_MANAGER` and :kconfig:option:`CONFIG_SENSOR` Kconfig options. diff --git a/doc/nrf/libraries/dfu/pcd.rst b/doc/nrf/libraries/dfu/pcd.rst index c5d35e66acb..8ebf9cc93f2 100644 --- a/doc/nrf/libraries/dfu/pcd.rst +++ b/doc/nrf/libraries/dfu/pcd.rst @@ -7,7 +7,7 @@ Peripheral CPU DFU (PCD) :local: :depth: 2 -The peripheral CPU DFU (PCD) library provides functionality for transferring DFU images from the application core to the network core on the nRF5340 System on Chip (SoC). +The peripheral CPU DFU (PCD) library provides functionality for transferring DFU images from the application core to the network core on the nRF5340 System-on-Chip (SoC). Overview ******** diff --git a/doc/nrf/libraries/modem/location.rst b/doc/nrf/libraries/modem/location.rst index ffc8282ad58..a316bcbe7b6 100644 --- a/doc/nrf/libraries/modem/location.rst +++ b/doc/nrf/libraries/modem/location.rst @@ -60,6 +60,14 @@ The supported location methods are as follows: The ``cloud location`` method handles the location methods (cellular and Wi-Fi positioning) that scan for technology-specific information and sends it over to the cloud service for location resolution. +If the following conditions are met, Wi-Fi and cellular scan results are combined into a single cloud request: + +* Methods are one after the other in the location request method list. +* Location request mode is :c:enum:`LOCATION_REQ_MODE_FALLBACK`. +* Requested cloud service for Wi-Fi and cellular is the same. + +A special :c:enum:`LOCATION_METHOD_WIFI_CELLULAR` method can appear within the :c:struct:`location_event_data` structure, +but it cannot be added into the location configuration passed to the :c:func:`location_request` function. The default priority order of location methods is GNSS positioning, Wi-Fi positioning and Cellular positioning. If any of these methods are disabled, the method is simply omitted from the list. @@ -122,6 +130,8 @@ The following diagram shows successful cellular positioning. The following diagram depicts a failure to find the GNSS fix, followed by a fallback to cloud positioning. Since the Wi-Fi and cellular positioning methods are one after another, they are combined to a single cloud positioning request. Both Wi-Fi APs and LTE cells are given to the application with a single :c:enum:`LOCATION_EVT_CLOUD_LOCATION_EXT_REQUEST` event. +The :c:enum:`LOCATION_EVT_STARTED` and the :c:enum:`LOCATION_EVT_FALLBACK` events are sent, +if the :kconfig:option:`CONFIG_LOCATION_DATA_DETAILS` Kconfig option is set. .. msc:: hscale="1.3"; @@ -132,6 +142,7 @@ Both Wi-Fi APs and LTE cells are given to the application with a single :c:enum: Application => Loclib [label="location_request(&config)\nmethod list: GNSS, Wi-Fi, Cellular"]; |||; + Application << Loclib [label="LOCATION_EVT_STARTED"]; Application << Loclib [label="LOCATION_EVT_GNSS_ASSISTANCE_REQUEST"]; Application => Cloud [label="Request A-GNSS data"]; Application << Cloud [label="A-GNSS data"]; @@ -141,6 +152,7 @@ Both Wi-Fi APs and LTE cells are given to the application with a single :c:enum: Loclib rbox Loclib [label="GNSS timeout occurs"]; Loclib rbox Loclib [label="Fallback to cloud positioning"]; + Application << Loclib [label="LOCATION_EVT_FALLBACK"]; Loclib rbox Loclib [label="Scan Wi-Fi and LTE networks"]; |||; Application << Loclib [label="LOCATION_EVT_CLOUD_LOCATION_EXT_REQUEST"]; @@ -221,7 +233,7 @@ Configure the following Kconfig options to enable Wi-Fi interface: * :kconfig:option:`CONFIG_WIFI` - Enable Wi-Fi for Zephyr. -The chosen Wi-Fi device needs to be set in Devicetree: +The chosen Wi-Fi device needs to be set in devicetree: .. code-block:: devicetree @@ -292,6 +304,10 @@ when :c:func:`location_config_defaults_set` function is called: * :kconfig:option:`CONFIG_LOCATION_REQUEST_DEFAULT_CELLULAR_CELL_COUNT` * :kconfig:option:`CONFIG_LOCATION_REQUEST_DEFAULT_WIFI_TIMEOUT` +The following option adds more details to the :c:struct:`location_event_data` structure: + +* :kconfig:option:`CONFIG_LOCATION_DATA_DETAILS` + Usage ***** diff --git a/doc/nrf/libraries/modem/lte_lc.rst b/doc/nrf/libraries/modem/lte_lc.rst index eb0ad74ebc3..e491dc4abb2 100644 --- a/doc/nrf/libraries/modem/lte_lc.rst +++ b/doc/nrf/libraries/modem/lte_lc.rst @@ -101,6 +101,8 @@ The following list mentions some of the information that can be extracted from t Some of the functionalities might not be compatible with certain modem firmware versions. To check if a desired feature is compatible with a certain modem firmware version, see the AT commands that are documented in the `nRF91x1 AT Commands Reference Guide`_ or `nRF9160 AT Commands Reference Guide`_ depending on the SiP you are using. +.. _lte_lc_power_saving: + Enabling power-saving features ============================== @@ -199,6 +201,12 @@ These callbacks allow any part of the application to perform certain operations For example, one kind of operation that the application or a library may need to perform and repeat, whenever the modem enters a certain functional mode is the subscription to AT notifications. The application can set up a callback for modem`s functional mode changes using the :c:macro:`LTE_LC_ON_CFUN` macro. +.. important:: + When the :c:macro:`LTE_LC_ON_CFUN` macro is used, the application must not call :c:func:`nrf_modem_at_cfun_handler_set` as that will override the handler set by the modem library integration layer. + +.. note:: + The CFUN callback is not supported with :c:func:`nrf_modem_at_cmd_async`. + The following code snippet shows how to use the :c:macro:`LTE_LC_ON_CFUN` macro: .. code-block:: c diff --git a/doc/nrf/libraries/modem/modem_antenna.rst b/doc/nrf/libraries/modem/modem_antenna.rst index 133e2cd8236..cebaa521dbb 100644 --- a/doc/nrf/libraries/modem/modem_antenna.rst +++ b/doc/nrf/libraries/modem/modem_antenna.rst @@ -25,8 +25,7 @@ Configuration Set the :kconfig:option:`CONFIG_MODEM_ANTENNA` Kconfig option to enable this library. .. note:: - - The library is enabled by default when building for targets ``nrf9161dk_nrf9161_ns``, ``nrf9160dk_nrf9160_ns``, and ``thingy91_nrf9160_ns``. + The library is enabled by default when building for the nRF91 Series build targets. Use one of the following options to select the used antenna type: diff --git a/doc/nrf/libraries/modem/modem_battery.rst b/doc/nrf/libraries/modem/modem_battery.rst index fea9dda2d00..5cf0455c4a1 100644 --- a/doc/nrf/libraries/modem/modem_battery.rst +++ b/doc/nrf/libraries/modem/modem_battery.rst @@ -13,7 +13,7 @@ The library issues AT commands to perform the following actions: * Retrieve the battery voltage measured by the modem. * Set the battery voltage low level for the modem using the ``%XVBATLOWLVL`` command. - See the `Battery voltage low level %XVBATLOWLVL`_ section in the nRF9160 AT Commands Reference Guide or the same section in the `nRF91x1 AT Commands Reference Guide`_ depending on the SiP you are using. + See the `Battery voltage low level %XVBATLOWLVL`_ section in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. * Subscribe to or unsubscribe from unsolicited notifications on modem battery voltage low level. * Configure the power-off warnings from the modem (possible with modem firmware v1.3.1 and higher). diff --git a/doc/nrf/libraries/modem/modem_key_mgmt.rst b/doc/nrf/libraries/modem/modem_key_mgmt.rst index 1d7f8478e75..8df3a7a8eec 100644 --- a/doc/nrf/libraries/modem/modem_key_mgmt.rst +++ b/doc/nrf/libraries/modem/modem_key_mgmt.rst @@ -9,7 +9,7 @@ Modem key management The modem key management library provides functions to manage the credentials stored in the nRF91 Series LTE modem. The library uses credential storage management to add, update, and delete credentials using the ``%CMNG`` command. -See the `Credential storage management %CMNG`_ section in the nRF9160 AT Commands Reference Guide or the same section in the `nRF91x1 AT Commands Reference Guide`_ depending on the SiP you are using. +See the `Credential storage management %CMNG`_ section in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. Each set of keys and certificates that is stored in the modem is identified by a security tag (``sec_tag``). You specify this tag when adding the credentials and use it when you update or delete them. @@ -32,30 +32,28 @@ Certificates come in different formats. To provision the certificate to the nRF91 Series DK, it must be in PEM format. The PEM format looks like this:: - "-----BEGIN CERTIFICATE-----\n" - "MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G\n" - "A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp\n" - "Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1\n" - "MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG\n" - "A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\n" - "hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL\n" - "v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8\n" - "eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq\n" - "tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd\n" - "C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa\n" - "zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB\n" - "mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH\n" - "V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n\n" - "bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG\n" - "3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs\n" - "J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO\n" - "291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS\n" - "ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd\n" - "AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7\n" - "TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==\n" - "-----END CERTIFICATE-----\n" - -Note the ``\n`` at the end of each line. + -----BEGIN CERTIFICATE----- + MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G + A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp + Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 + MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG + A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI + hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL + v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 + eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq + tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd + C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa + zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB + mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH + V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n + bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG + 3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs + J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO + 291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS + ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd + AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 + TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== + -----END CERTIFICATE----- See the comprehensive `tutorial on SSL.com`_ for instructions on how to convert between different certificate formats and encodings. diff --git a/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_trace.rst b/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_trace.rst index d79d7b55b7e..f8d91a52782 100644 --- a/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_trace.rst +++ b/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_trace.rst @@ -80,7 +80,9 @@ The modem trace flash backend has some additional configuration options: * :kconfig:option:`CONFIG_FCB` - Required for the flash circular buffer used in the backend. * :kconfig:option:`CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_FLASH_PARTITION_SIZE` - Defines the space to be used for the modem trace partition. - The external flash size on the nRF9160 DK is 8 MB (equal to ``0x800000`` in HEX). + In order to improve the modem trace write performance, this partition is erased during system boot. + This might lead to a significant increase in the boot time on the nRF9160 DK. + The external flash size on the nRF9160 DK is 8 MB (equal to ``0x800000`` in HEX) and 32 MB on the nRF9161 DK (equal to ``0x2000000`` in HEX). It is also recommended to enable high drive mode and high-performance mode in devicetree. High drive is to ensure that the communication with the flash device is reliable at high speed. @@ -173,7 +175,7 @@ To enable modem traces with RTT, enable the :kconfig:option:`CONFIG_NRF_MODEM_LI The traces can be captured using the J-Link RTT logger software. This produces a RAW binary trace file with a ``.log`` extension. -The RAW binary trace file can be converted to PCAP with the :guilabel:`Convert RAW trace to PCAP` option in the Trace Collector application of `nRF Connect for Desktop`_. +The RAW binary trace file can be converted to PCAP with the :guilabel:`Open trace file in Wireshark` option in the `Cellular Monitor`_ app of `nRF Connect for Desktop`_. By default, files with the ``.log`` extension are not shown. .. _adding_custom_modem_trace_backends: @@ -316,3 +318,45 @@ Complete the following steps to add a custom trace backend: CONFIG_NRF_MODEM_LIB_TRACE=y CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_MY_TRACE_BACKEND=y + +.. _modem_trace_shell_command: + +Modem trace shell command +************************* + +Shell command: ``modem_trace`` + +You can use the modem trace commands to control the trace functionality in the modem when the :kconfig:option:`CONFIG_NRF_MODEM_LIB_SHELL_TRACE` Kconfig option is enabled. +A trace backend that can store modem traces is required to send modem traces to the cloud. +The ``modem_trace dump_uart`` command is a simple demonstration of how trace data can be read out from storage using the :c:func:`nrf_modem_lib_trace_read` function. + +Be aware that the default trace level is :kconfig:option:`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_FULL` and starts modem traces during system boot automatically. +In case you want to start modem tracing using shell commands instead, set the :kconfig:option:`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_OFF` Kconfig option to ``y``. + +Following are some examples of modem tracing: + +* To trace everything (LTE, IP, and GNSS): + + .. code-block:: console + + modem_trace start full + + modem_trace stop + +* To read out the size of stored modem traces: + + .. code-block:: console + + modem_trace size + +* To read out stored traces and send over UART: + + .. code-block:: console + + modem_trace dump_uart + +* To delete all stored modem traces: + + .. code-block:: console + + modem_trace clear diff --git a/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_wrapper.rst b/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_wrapper.rst index 6f05e9fd906..1331ebcc9ab 100644 --- a/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_wrapper.rst +++ b/doc/nrf/libraries/modem/nrf_modem_lib/nrf_modem_lib_wrapper.rst @@ -22,10 +22,14 @@ When using the Modem library in |NCS|, the library must be initialized and shutd .. _mlil_callbacks: -Callbacks -********* +Modem library callbacks +*********************** + +The library wrapper provides callbacks for the modem initialization and shutdown operations, as well as macros for registering multiple callbacks on changes to the modem functional mode. + +Modem initialization and shutdown +================================= -The library wrapper also provides callbacks for the initialization and shutdown operations. The application can set up a callback for the :c:func:`nrf_modem_lib_init` function using the :c:macro:`NRF_MODEM_LIB_ON_INIT` macro, and a callback for :c:func:`nrf_modem_lib_shutdown` function using the :c:macro:`NRF_MODEM_LIB_ON_SHUTDOWN` macro. These compile-time callbacks allow any part of the application to perform any setup steps that require the modem to be in a certain state. Furthermore, the callbacks ensure that the setup steps are repeated whenever another part of the application turns the modem on or off. @@ -43,3 +47,18 @@ The callbacks registered using the :c:macro:`NRF_MODEM_LIB_ON_SHUTDOWN` macro ar The callback context is provided to these callbacks. Callbacks for the macro :c:macro:`NRF_MODEM_LIB_ON_SHUTDOWN` must have the signature ``void callback_name(void *ctx)``, where ``ctx`` is the context passed to the macro. See the :ref:`modem_callbacks_sample` sample for more information. + +Modem functional mode changes +============================= + +The application can set up a callback for AT CFUN calls using the :c:macro:`NRF_MODEM_LIB_ON_CFUN` macro. +This compile-time callback allows any part of the application to perform any steps that are required when the modem changes functional mode. +The callbacks registered using the :c:macro:`NRF_MODEM_LIB_ON_CFUN` macro are executed after the functional mode has been successfully set. +See the :ref:`modem_callbacks_sample` sample for more information. + +.. important:: + The application should not call :c:func:`nrf_modem_at_cfun_handler_set` as that will override the handler set by the modem library integration layer. + Instead, the application should use the :c:macro:`NRF_MODEM_LIB_ON_CFUN` macro to register functional mode changes. + +.. note:: + The CFUN callback is not supported with :c:func:`nrf_modem_at_cmd_async`. diff --git a/doc/nrf/libraries/modem/pdn.rst b/doc/nrf/libraries/modem/pdn.rst index 4ebb3bde00a..f0fa0b938d0 100644 --- a/doc/nrf/libraries/modem/pdn.rst +++ b/doc/nrf/libraries/modem/pdn.rst @@ -17,13 +17,12 @@ It provides an API for the following purposes: The library uses several AT commands, and it relies on the following two types of AT notifications to work: * Packet domain events notifications (``+CGEV``) - Subscribed by using the ``AT+CGEREP=1`` command. - See the `AT+CGEREP set command`_ section in the nRF9160 AT Commands Reference Guide or the same section in the `nRF91x1 AT Commands Reference Guide`_ depending on the SiP you are using. + See the `AT+CGEREP set command`_ section in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. * Notifications for unsolicited reporting of error codes sent by the network (``+CNEC``) - Subscribed by using the ``AT+CNEC=16`` command. - See the `AT+CNEC set command`_ section in the nRF9160 AT Commands Reference Guide or the same section in the `nRF91x1 AT Commands Reference Guide`_ depending on the SiP you are using. + See the `AT+CNEC set command`_ section in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. -If the application uses the :ref:`lte_lc_readme` library to change the modem's functional mode, the PDN library automatically subscribes to the necessary AT notifications. +The PDN library automatically subscribes to the necessary AT notifications using :ref:`mlil_callbacks`. This includes automatically resubscribing to the notifications upon functional mode changes. -If the application does not use the :ref:`lte_lc_readme` library to change the modem's functional mode, the application must subscribe to the necessary AT notifications manually. .. note:: The subscription to AT notifications is lost upon changing the modem functional mode to ``+CFUN=0``. @@ -37,7 +36,7 @@ Following are the AT commands that are used by the library: * ``AT%XGETPDNID``- To retrieve the PDN ID for a given PDP context * ``AT+CGAUTH`` - To set the PDN connection authentication parameters -For more information about these commands, see `Packet Domain AT commands`_ in the nRF9160 AT Commands Reference Guide or the same section in the `nRF91x1 AT Commands Reference Guide`_ depending on the SiP you are using. +For more information about these commands, see `Packet Domain AT commands`_ in the nRF9160 AT Commands Reference Guide or the `same section `_ in the nRF91x1 AT Commands Reference Guide, depending on the SiP you are using. The application can create PDP contexts by using the :c:func:`pdn_ctx_create` function, and a callback can be assigned to receive the events pertaining to the state and connectivity of the PDP contexts. The application can use the :c:func:`pdn_default_ctx_cb_reg` function to register an event handler for events pertaining the default PDP context, and the :c:func:`pdn_default_ctx_cb_dereg` to deregister it. diff --git a/doc/nrf/libraries/networking/aws_fota.rst b/doc/nrf/libraries/networking/aws_fota.rst index bd97e397691..a8381bd12fa 100644 --- a/doc/nrf/libraries/networking/aws_fota.rst +++ b/doc/nrf/libraries/networking/aws_fota.rst @@ -58,9 +58,6 @@ Creating a FOTA job #. Click :guilabel:`Objects` to go back to the bucket. #. Click :guilabel:`Upload` and :guilabel:`Add files`. #. Select the file :file:`app_update.bin` (located in the :file:`zephyr` subfolder of your build directory). - - If you want to update the modem firmware, extract the content of a downloaded modem firmware zip and select the desired delta update, for example :file:`mfw_nrf9160_update_from_1.3.1_to_1.3.2`. - The various modem firmware versions can be found in `nRF9160 DK Downloads`_ for the nRF9160 DK, and `nRF9161 DK Downloads`_ for the nRF9161 DK. #. Click :guilabel:`Upload` and then :guilabel:`Close`. #. Click the uploaded image file :file:`app_update.bin` and copy the *Object URL* without the *https://* prefix and folder path. #. Create a text file (job document) with content as in the snippet, replacing the following data: @@ -98,20 +95,7 @@ Creating a FOTA job After the job has been submitted, the device picks up the job automatically. This can take several minutes. In the `AWS S3 console`_ you can check the status of the job to confirm that it is in progress. - -Troubleshooting -=============== - -ERROR: -NRF_ECONNREFUSED: - Error -NRF_ECONNREFUSED ("Connection refused") indicates an error with the configured certificates. - -ERROR: -NRF_EHOSTUNREACH: - Error -NRF_EHOSTUNREACH ("Host is unreachable") indicates that the download URL provided in the job document is wrong. - -Content range is not defined: - If you host the firmware image on a different server than in an S3 bucket, this error indicates that the Content-Range field is missing in the HTTP GET header. - To fix this problem, configure the host server to provide this field. - Also, confirm that your file is available from the browser without being logged into your AWS account. +To handle the failed statuses, see :ref:`aws_fota_troubleshooting`. Configuration ************* @@ -181,6 +165,36 @@ Alternatively, to use a single URL, a document like the following can be used: For information on how to use presigned AWS S3 URLs, refer to `AWS IoT Developer Guide: Managing Jobs`_. +.. _aws_fota_troubleshooting: + +Troubleshooting +*************** + +The following sections list some common errors and possible solutions to them. + +Known error codes +================= + +ERROR: ``-NRF_ECONNREFUSED``: + Connection refused - This indicates an error with the configured certificates. + +ERROR: ``-NRF_EHOSTUNREACH``: + Host is unreachable - This indicates that the download URL provided in the job document is wrong. + +Content range is not defined: + If you host the firmware image on a different server than in an S3 bucket, this error indicates that the Content-Range field is missing in the HTTP GET header. + To fix this problem, configure the host server to provide this field. + Also, confirm that your file is available from the browser without being logged into your AWS account. + +Presigned URLs +============== + +When using the presigned URLs, you might need to increase the value of the following Kconfig options to accommodate the long file name and payload size of the presigned URL and the secure download of the image: + +* :kconfig:option:`CONFIG_DOWNLOAD_CLIENT_MAX_FILENAME_SIZE`. +* :kconfig:option:`CONFIG_AWS_FOTA_PAYLOAD_SIZE`. +* :kconfig:option:`CONFIG_MBEDTLS_HEAP_SIZE` - If running Mbed TLS on the application core (Wi-Fi® builds). + Limitations *********** diff --git a/doc/nrf/libraries/networking/aws_iot.rst b/doc/nrf/libraries/networking/aws_iot.rst index eee9d6c7655..38727284df1 100644 --- a/doc/nrf/libraries/networking/aws_iot.rst +++ b/doc/nrf/libraries/networking/aws_iot.rst @@ -103,7 +103,7 @@ There are multiple ways to generate and register these certificates: .. code-block:: console - aws iot create-certificate-from-csr --certificate-signing-request device_cert.csr.pem --certificate-pem-outfile device_cert.pem --set-as-active --no-cli-pager --query certificateArn + aws iot create-certificate-from-csr --certificate-signing-request file://device_cert.csr.pem --certificate-pem-outfile device_cert.pem --set-as-active --no-cli-pager --query certificateArn #. Take note of the certificate ARN, as it will be required later. #. Provision the certificate using the following command: @@ -188,9 +188,9 @@ There are multiple ways to generate and register these certificates: #. Take note of the certificate ARN, as it will be required later. #. Download the `Amazon Root CA 1`_ PEM file as :file:`ca-cert.pem`. - #. Provision the certificates and private key at runtime to the Mbed TLS stack. - This is achieved by placing the PEM files into a :file:`certs/` subdirectory and ensuring the :kconfig:option:`CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES` Kconfig option is enabled. - For more information, refer to the :ref:`aws_iot` sample as well as the :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FILE` Kconfig option. + #. Place the PEM files into the folder path specified by the :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FOLDER` option, default is :file:`/certs/`. + Ensure that the :kconfig:option:`CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES` option is set. + #. If the files are placed correctly, the :ref:`lib_mqtt_helper` library finds the certificates and provisions them to the Mbed TLS stack when connecting to AWS IoT. .. rst-class:: numbered-step diff --git a/doc/nrf/libraries/networking/azure_iot_hub.rst b/doc/nrf/libraries/networking/azure_iot_hub.rst index 5216cbf81c0..2e47635f396 100644 --- a/doc/nrf/libraries/networking/azure_iot_hub.rst +++ b/doc/nrf/libraries/networking/azure_iot_hub.rst @@ -24,105 +24,501 @@ For more information on how Azure SDK for Embedded C is integrated in this libra If the server sends a device-bound message when the device is unavailable for a period of time, for instance while in LTE Power Saving Mode, the server will most likely terminate the TCP connection. This will result in additional data traffic as the device has to reconnect to the server, which in turn requires a new TLS handshake and MQTT connection establishment. - .. _prereq_connect_to_azure_iot_hub: -Prerequisites for connecting to Azure IoT Hub -********************************************* +Setup and configuration +*********************** + +To connect a device to Azure IoT Hub, complete the following steps: + +1. :ref:`azure_set_up` +#. :ref:`azure_authenticate` +#. :ref:`azure_create_iot_hub` +#. :ref:`azure_generating_certificates` +#. :ref:`azure_create_device` +#. :ref:`azure_iot_hub_flash_certs` + +.. rst-class:: numbered-step + +.. _azure_set_up: + +Setting up Azure IoT Hub +======================== + +If you do not have an Azure account, you need to create one. + +To get started with testing the Azure IoT Hub, make sure that the following prerequisites are met: + +* Install the `Azure CLI`_. +* To use the ``nrfcredstore`` tool, the dependencies in the :file:`nrf/scripts/requirements-extra.txt` file must be installed. + +.. rst-class:: numbered-step + +.. _azure_authenticate: + +Authenticate Azure CLI +====================== + +Authenticate the Azure CLI tool to use your Azure account in the default browser with the following command: + +.. code-block:: console + + az login + +For other authentication options, see the `Sign in with Azure CLI`_ documentation. + +.. rst-class:: numbered-step + +.. _azure_create_iot_hub: + +Create an IoT Hub +================= + +1. When creating an IoT Hub, you must create it in a resource group. + You can create a resource group through Azure's CLI using the following command: -In order to connect to Azure IoT Hub, an Azure account and an Azure IoT Hub instance must first be created and configured. -See `Creating an Azure IoT Hub instance using the Azure portal`_ for more information. + .. code-block:: console + + az group create --name --location westus + + If you want to use another region than ``westus``, you can acquire a list of the available locations by running the following command: + + .. code-block:: console + + az account list-locations -o table + + +#. To create an IoT Hub, use the following command, select the resource group you created, and create a unique name for your IoT Hub: + + .. code-block:: console + + az iot hub create --resource-group --name --sku F1 --partition-count 2 + + Using ``F1`` as an argument creates a free IoT Hub, which allows you to have only one instance. + Hence, delete your existing free IoT Hub or change the SKU to ``S1``. + +For information on how to set up creating an Azure IoT Hub instance using the Azure portal, see `Creating an Azure IoT Hub instance using the Azure portal`_. + +.. rst-class:: numbered-step + +.. _azure_generating_and_provisioning_certificates: +.. _azure_generating_certificates: + +Generating certificates +======================= + +The connection to the Azure IoT Hub with MQTT is secured using TLS. +To create the device certificate, you need a Certificate Authority (CA) certificate and a private key that is used to sign all of your client certificates. +The CA certificate is uploaded to Azure IoT Hub, so Azure can verify that the device certificate is signed by your CA. +If you do not have a CA certificate, you can purchase one or make a self-signed test CA certificate for testing purposes. + +To help generate test CA certificates and handle the device keys and certificates, you can use the :file:`nrf/scripts/cert_tool.py` Python script. +Either call the script relative from the current working directory or add it to the path. .. note:: - If you do not use DPS to provision devices to your IoT Hub, make sure that you select ``X.509 CA Signed`` as the *Authentication type* while `Registering the device with Azure IoT Hub`_. + The :file:`cert_tool.py` Python script has default values for all actions for the input and output file names. + See the available arguments by running the ``--help`` argument to the script. + +Generate test CA certificates +----------------------------- + +* To generate the root CA certificate, use the following command: + + .. code-block:: console + + cert_tool.py root_ca + + This command generates a self-signed root CA certificate and private key and saves them to the files :file:`ca/root-ca-cert.pem` and :file:`ca/root-ca-key.pem`. + +* To generate the subordinate CA certificate, use the following command: + + .. code-block:: console + + cert_tool.py sub_ca + + This command generates a subordinate CA certificate (signed by the root CA) and private key and saves them to the files :file:`ca/sub-ca-cert.pem` and :file:`ca/sub-ca-key.pem`. + +Upload and verify the root CA certificate +----------------------------------------- + +To perform proof of possession of the root CA key, you can verify the root CA certificate using the following set of commands: + +* To upload root CA certificate:: + + az iot hub certificate create --hub-name --name --path ca/root-ca-cert.pem + +* To ask Azure for a verification code (need two output values):: + + az iot hub certificate generate-verification-code --hub-name --name --etag "" + + Note down the verification code and etag for later use. + +* To generate a new private key:: + + cert_tool.py client_key + +* To Create a CSR with the verification code as common name:: + + cert_tool.py csr --common-name + +* To Sign the CSR with the root CA:: + + cert_tool.py sign_root + +* To Upload the verification certificate:: + + az iot hub certificate verify --hub-name --name --etag "" --path certs/client-cert.pem + +.. _azure_device_provisioning: + +Setup Device Provisioning Service (DPS) +--------------------------------------- + +If you are using DPS to provision devices to your IoT hub, you need to set up an Azure IoT Hub Device Provisioning Service (DPS) instance. + +There are many ways to configure DPS. +Attestation using the subordinate CA certificate is one of them. +For other DPS configurations, see the `Azure IoT Hub Device Provisioning Service (DPS)`_ documentation. + +Use the following commands to set up DPS using a subordinate CA certificate for attestation: + +* To create the DPS instance:: + + az iot dps create --name --resource-group + +* To link the IoT Hub to the DPS instance:: + + az iot dps linked-hub create --dps-name --hub-name --resource-group + +* To Create an enrollment group:: + + az iot dps enrollment-group create --dps-name --resource-group --enrollment-id --certificate-path ca/sub-ca-cert.pem --provisioning-status enabled --iot-hubs --allocation-policy static + +.. _azure_generate_certificates: + +Generate and provision device certificates +------------------------------------------ + +The following are the ways to generate and register device certificates: + +* The device key and certificate are generated using the :file:`cert_tool.py` script and provisioned to the device. +* The device generates a key and a Certificate Signing Request (CSR). + This method is more secure because the private key never leaves the device. + +.. tabs:: + + .. tab:: nRF91: Modem generated private key + + When the private key is generated inside the modem, it is never exposed to the outside world. + This is more secure than generating a private key using a script. + By default, the Common Name (CN) of the certificate is set to the device UUID, and the CN is read out by Azure to identify the device during the TLS handshake. + This allows using the exact same firmware on many devices without hard-coding the device ID into the firmware because the device UUID can be read out at runtime. + See the :ref:`azure_iot_hub` sample for more information on how to read out the device UUID in the application. + + .. note:: + Generating a key pair on device requires an nRF91 Series device. + If you are using an nRF9160 DK, modem version v1.3.x or later is required. + + .. important:: + Program the :ref:`at_client_sample` sample to your device before following this guide. + + Complete the following steps to generate a key pair and CSR on the modem, which is then signed using your CA and uploaded to Azure: + + 1. Obtain a list of installed keys using the following command: + + .. code-block:: console + + nrfcredstore list + + where ```` is the serial port of your device. + + #. Select a security tag that is not yet in use. + This security tag must match the value set in the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option. + + #. Generate a key pair and obtain a CSR using the following command: + + .. code-block:: console + + nrfcredstore generate certs/client-csr.der -The connection to Azure IoT Hub with MQTT is secured using TLS. -For testing purposes, see `Creating Azure IoT Hub certificates`_ for the steps to create certificates and a private key for the leaf device, and to register the generated test root certificate to be used with an IoT hub. + |serial_port_sec_tag| + + #. Convert the CSR from DER format to PEM format using the following command: + + .. code-block:: console + + openssl req -inform DER -in certs/client-csr.der -outform PEM -out certs/client-csr.pem + + #. Sign the CSR using the subordinate CA certificate using the following command: + + .. code-block:: console + + cert_tool.py sign + + .. note:: + This process might vary depending on the CA you are using. + See the documentation for your CA for more information on how to sign a CSR. + + #. Take note of the CN, as it will be required later. + + In case you got the certificate from a CA, you can extract the CN using the following command: + + .. code-block:: console + + openssl x509 -in certs/client-cert.pem -noout -subject + + #. Provision the certificate to the modem using the following command: + + .. code-block:: console + + nrfcredstore write CLIENT_CERT certs/client-cert.pem + + |serial_port_sec_tag| + + .. tab:: nRF91: Script generated private key + + .. caution:: + When generating the private key on your computer, make sure to keep it secure and not share it with anyone. + If the private key is compromised, the security of the device is compromised. + + .. important:: + Program the :ref:`at_client_sample` sample to your device before following this guide. + + To obtain a key and certificate generated by the :file:`cert_tool.py` script and to provision them to the modem, complete the following steps: + + 1. Generate the key and certificate using the following commands: + + .. code-block:: console + + cert_tool.py client_key + cert_tool.py csr --common-name + cert_tool.py sign + + This command generates an elliptic curve private key and saves it to the :file:`certs/private-key.pem` file. + The certificate is saved to the :file:`certs/client-cert.pem` file. + + #. Obtain a list of installed keys using the following command: + + .. code-block:: console + + nrfcredstore list + + where ```` corresponds to the serial port of your device. + + #. Select a security tag that is not yet in use. + This security tag must match the value set in :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option. + + #. Provision the client certificate using the following command: + + .. code-block:: console + + nrfcredstore write CLIENT_CERT certs/client-cert.pem + + |serial_port_sec_tag| + + #. Provision the client key using the following command: + + .. code-block:: console + + nrfcredstore write CLIENT_KEY certs/private-key.pem + + |serial_port_sec_tag| + + .. tab:: nRF70: Script generated private key + + .. caution:: + When generating the private key on your computer, make sure to keep it secure and not share it with anyone. + If the private key is compromised, the security of the device is compromised. + + To obtain a key and certificate generated using the :file:`cert_tool.py` script, complete the following steps: + + 1. Generate the key and certificate using the following commands: + + .. code-block:: console + + cert_tool.py client_key + cert_tool.py csr --common-name + cert_tool.py sign + + #. Provision the certificates and private key at runtime to the Mbed TLS stack. + This is achieved by placing the PEM files into a :file:`certs/` subdirectory and ensuring the :kconfig:option:`CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES` Kconfig option is enabled. + For more information, refer to the :ref:`azure_iot_hub` sample as well as the :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FILE` Kconfig option. + +.. rst-class:: numbered-step + +.. _azure_create_device: + +Register a device in Azure IoT Hub +================================== + +.. tabs:: + + .. tab:: Enroll using DPS + + .. code-block:: console + + az iot dps enrollment create --enrollment-id --device-id --provisioning-status enabled --resource-group --iot-hubs --attestation-type x509 --certificate-path certs/client-cert.pem --dps-name --allocation-policy static + + .. tab:: Register each device by device ID + + .. important:: + The device ID must match the CN of the certificate. + + To register a new device in your IoT hub, use the following command: + + .. code-block:: console + + az iot hub device-identity create -n -d --am x509_ca + + +.. rst-class:: numbered-step + +.. _azure_iot_hub_flash_certs: + +Provision root CA certificates +============================== The Azure IoT Hub library requires provisioning of the following certificates and a private key for a successful TLS connection: -1. `Baltimore CyberTrust Root Certificate`_ - Server certificate, used to verify the server's certificate while connecting. -#. Public device certificate - generated by the procedures described in `Creating Azure IoT Hub certificates`_ , used by Azure IoT Hub to authenticate the device. +1. `DigiCert Global Root G2`_ - The root CA certificate used to verify the server's certificate chain while connecting. +#. `Baltimore CyberTrust Root Certificate`_ - Azure's legacy root CA certificate needed to verify the Azure server's that have not migrated to `DigiCert Global Root G2`_ yet. +#. Device certificate - Generated by the procedures described in :ref:`azure_generate_certificates`, used by Azure IoT Hub to authenticate the device. #. Private key of the device. .. important:: - Azure has started the process of migrating their IoT Hub and DPS server certificates from `Baltimore CyberTrust Root Certificate`_ to `DigiCert Global Root G2`_. + Azure has started the process of migrating their DPS server certificates from `Baltimore CyberTrust Root Certificate`_ to `DigiCert Global Root G2`_. + Azure IoT Hub servers have finished this transition, and only DigiCert Global Root G2 is used now for those connections. Azure advises to have both Baltimore CyberTrust Root and DigiCert Global Root G2 certificates for all devices to avoid disruption of service during the transition. Refer to `Azure IoT TLS: Critical changes`_ for updated information and timeline. - Due to this, it is recommended to provision the DigiCert Root G2 certificate to a secondary security tag set by the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` option. - This ensures that the device can connect after the transition. + Due to this, it is recommended to provision the Baltimore CyberTrust Root Certificate to a secondary security tag set by the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` option. + This ensures that the device can also connect after the transition. +To provision the certificates, use any of the following methods, depending on the DK you are using. -The location and name of the generated public device certificate and private key files vary depending on the method you use for the credential generation as follows: +.. tabs:: -* For PowerShell scripts, the device certificate is called :file:`mydevice-public.pem` and the private key is :file:`mydevice-private.pem`. + .. tab:: nRF91: ``nrfcredstore`` - These files are located in the working directory with the other generated files. + .. important:: + Program the :ref:`at_client_sample` sample to your device before following this guide and make sure you have ``nrfcredstore`` installed. -* For bash scripts, the public device certificate is called :file:`new-device.cert.pem` and is located in a directory called :file:`certs` within the :file:`script` directory. + 1. Obtain a list of installed keys using the following command: - The private key is called :file:`new-device.key.pem` and located in a directory called :file:`private` within the :file:`script` directory. + .. code-block:: console -The file and directory names may change if Azure changes their scripts. + nrfcredstore list + where ```` is the serial port of your device. -.. _azure_iot_hub_flash_certs: + #. Provison the server root CA certificates, which you downloaded previously, by running the following commands: + + .. code-block:: console + + nrfcredstore write ROOT_CA_CERT DigiCertGlobalRootG2.crt.pem + + .. code-block:: console + + nrfcredstore write ROOT_CA_CERT BaltimoreCyberTrustRoot.crt.pem + + + .. tab:: nRF91: nRF connect for Desktop + + .. include:: /includes/cert-flashing.txt + + .. tab:: nRF70: runtime provisioning -Provisioning of the certificates -================================ + Provision the certificates and private key at runtime to the Mbed TLS stack. + This is achieved by placing the PEM files into a :file:`certs/` subdirectory and ensuring the :kconfig:option:`CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES` Kconfig option is enabled. + Save the :file:`DigiCertGlobalRootG2.crt.pem` file as :file:`certs/ca-cert.pem`, and the :file:`BaltimoreCyberTrustRoot.crt.pem` file as :file:`certs/ca-cert-2.pem`. + For more information, refer to the :ref:`azure_iot_hub` sample as well as the :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FILE` Kconfig option. -.. include:: /includes/cert-flashing.txt + The CA will be provisioned to the security tag set by the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option. The chosen security tag while provisioning the certificates must be the same as the security tag configured by the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` option. If more than one root server certificate is used, the second one can be provisioned to a different security tag and configured in the application using the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` Kconfig option. -The modem will check both security tags if necessary when verifying the server's certificate. +The modem checks both security tags if necessary when verifying the server's certificate. Configuring the library ======================= You can configure the library to connect to Azure IoT Hub with or without using DPS. -Configuration without using DPS -+++++++++++++++++++++++++++++++ +.. _dps_config: -To connect to Azure IoT Hub without using DPS, complete the following minimum required configuration: +.. tabs:: -1. In the `Azure Portal`_, navigate to :guilabel:`IoT Hub` and select the desired IoT hub. -#. In the overview page, locate and copy the ``Hostname`` and configure :kconfig:option:`CONFIG_AZURE_IOT_HUB_HOSTNAME` to this address. + .. tab:: Using DPS - You can also set the host name at run time. -#. Set the Kconfig option :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` to the device ID. + To connect to Azure IoT Hub using DPS, complete the following steps: - The device ID must match with the one used while creating the certificates. - You can also set the device ID at run time by populating the ``device_id`` member of the :c:struct:`azure_iot_hub_config` structure passed to the :c:func:`azure_iot_hub_connect` function when connecting. - If the ``device_id.size`` buffer size is zero, the compile-time option :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` is used. -#. Make sure that the device is already registered with your Azure IoT Hub, or follow the instructions in `Registering the device with Azure IoT Hub`_. -#. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option to the security tag used in :ref:`azure_iot_hub_flash_certs`. + 1. Set the :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_ID_SCOPE` Kconfig option to the ``ID Scope`` for your DPS instance by running the following command: - Optionally, set the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` Kconfig option if multiple server certificates are provisioned. + .. code-block:: console -.. _dps_config: + az iot dps show --name --query "properties.idScope" + + Alternatively, you can set the registration ID at runtime. + + #. Configure the registration ID: + + For testing on one device, you can manually configure the registration ID by setting the :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_REG_ID` Kconfig option. + + When running the same firmware on multiple devices, it is not practical to hard-code the registration ID. + Instead enable the use of a unique hardware identifier, such as the device UUID, as the registration ID. + The hardware identifier of the device needs to match the CN in the certificate on the device. + + .. tabs:: + + .. tab:: nRF91: Device UUID + + .. code-block:: none + + CONFIG_MODEM_JWT=y + CONFIG_HW_ID_LIBRARY_SOURCE_UUID=y + + .. tab:: nRF91: Device IMEI + + .. code-block:: none + + CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y + + .. tab:: nRF70: Network MAC address + + .. code-block:: none + + HW_ID_LIBRARY_SOURCE_NET_MAC=y + + + .. note:: + When using hardware identifiers in the :ref:`azure_iot_hub` sample, set the :kconfig:option:`CONFIG_AZURE_IOT_HUB_SAMPLE_DEVICE_ID_USE_HW_ID` Kconfig option to ``y``. + + You can also set the registration ID at runtime. + + #. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option to the security tag used while :ref:`provisioning root CA certificates `. + #. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` Kconfig option to the security tag of the extra root CA certificate until all Azure services have migrated to DigiCert Global Root G2. + + .. tab:: Without DPS + + To connect to Azure IoT Hub without using DPS, complete the following minimum required configuration: -Configuration using DPS -+++++++++++++++++++++++ + 1. To retrieve your IoT Hub hostname, run the following command: -To connect to Azure IoT Hub using DPS, complete the following steps: + .. code-block:: console -1. `Set up an Azure IoT Hub Device Provisioning Service (DPS) instance`_ and obtain the ID scope. -#. `Add certificates to the DPS instance`_. -#. Create an *enrollment group* as described in `Device enrollments with Azure Portal`_ and link it to your IoT hub. Select the certificate added in the previous step as the *Primary certificate​​​​​​​*. -#. Enable the :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS` Kconfig option. -#. In the `Azure Portal`_, click :guilabel:`Device Provisioning Services` and select the DPS instance to use. -#. In the overview page, locate and copy the ``ID Scope`` and set the :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_ID_SCOPE` Kconfig option to this string. + az iot hub show --name --query "properties.hostName" - Alternatively, you can set the registration ID at run time. -#. Set the :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_REG_ID` Kconfig option to the registration ID. + #. Configure the :kconfig:option:`CONFIG_AZURE_IOT_HUB_HOSTNAME` Kconfig option to the returned address. - You can also set the registration ID at run time. + You can also set the host name at runtime. + #. Set the Kconfig option :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` to the device ID. -#. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option to the security tag used while :ref:`azure_iot_hub_flash_certs`. - Optionally, set the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` Kconfig option if multiple server certificates are provisioned. + The device ID must match with the one used while creating the certificates. + You can also set the device ID at runtime by populating the ``device_id`` member of the :c:struct:`azure_iot_hub_config` structure passed to the :c:func:`azure_iot_hub_connect` function when connecting. + If the ``device_id.size`` buffer size is zero, the compile-time option :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` is used. + #. Make sure that the device is already registered with your Azure IoT Hub, or follow the instructions in :ref:`azure_create_device`. + #. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SEC_TAG` Kconfig option to the security tag used in :ref:`azure_iot_hub_flash_certs`. + #. Set the :kconfig:option:`CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG` Kconfig option to the security tag of the extra root CA certificate until all Azure services has migrated to DigiCert Global Root G2. Application integration *********************** @@ -248,9 +644,9 @@ Optionally, DPS registration can be run automatically as part of the call to the Use the DPS APIs directly if you need more control over the DPS registration process. -When using the :c:func:`azure_iot_hub_connect` function, you can choose to provide the host name to the IoT Hub and device ID at run time, or let the library use Kconfig options. +When using the :c:func:`azure_iot_hub_connect` function, you can choose to provide the host name to the IoT Hub and device ID at runtime, or let the library use Kconfig options. -Here is an example for setting the host name and device ID at run time: +Here is an example for setting the host name and device ID at runtime: .. code-block:: c @@ -303,8 +699,8 @@ To use the Azure IoT Hub library, you must enable the :kconfig:option:`CONFIG_AZ You can configure the following options when using this library: -* :kconfig:option:`CONFIG_AZURE_IOT_HUB_HOSTNAME` - Sets the Azure IoT Hub host name. Note that the host name can also be provided at run time. -* :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` - Configures the device ID. The device ID can also be set at run time. +* :kconfig:option:`CONFIG_AZURE_IOT_HUB_HOSTNAME` - Sets the Azure IoT Hub host name. Note that the host name can also be provided at runtime. +* :kconfig:option:`CONFIG_AZURE_IOT_HUB_DEVICE_ID` - Configures the device ID. The device ID can also be set at runtime. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_USER_NAME_BUF_SIZE` - Sets the user name buffer size. You can adjust the buffer size to reduce stack usage, if you know the approximate size of your device ID. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_AUTO_DEVICE_TWIN_REQUEST` - Automatically requests the device twin upon connection to an IoT Hub. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_TOPIC_MAX_LEN` - Sets the maximum topic length. The topic buffers are allocated on the stack. You may have to adjust this option to match with your device ID length. @@ -327,6 +723,7 @@ DPS-specific configuration: * :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS` - Enables Azure IoT Hub DPS. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_HOSTNAME` - Host name of the DPS server. + Do not change this unless you have configured DPS to use a different host name. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_REG_ID` - Registration ID to use in the registration request to DPS. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_HOSTNAME_MAX_LEN` - Maximum length of the assigned host name received from DPS. * :kconfig:option:`CONFIG_AZURE_IOT_HUB_DPS_DEVICE_ID_MAX_LEN` - Maximum length of the assigned device ID received from DPS. diff --git a/doc/nrf/libraries/networking/lwm2m_client_utils.rst b/doc/nrf/libraries/networking/lwm2m_client_utils.rst index 32396f7491b..3d639f1684c 100644 --- a/doc/nrf/libraries/networking/lwm2m_client_utils.rst +++ b/doc/nrf/libraries/networking/lwm2m_client_utils.rst @@ -7,14 +7,14 @@ LwM2M client utils :local: :depth: 2 -The LwM2M client utils library enables an nRF91 Series device to connect to an LwM2M server such as `Leshan Demo Server`_ using the Lightweight Machine to Machine (`LwM2M`_) protocol over LTE. +The LwM2M client utils library enables an nRF91 Series device to connect to an LwM2M Server such as `Leshan Demo Server`_ using the Lightweight Machine to Machine (`LwM2M`_) protocol over LTE. Once the device is connected, the library supports the querying the device to retrieve location data or information about the modem. This library builds on top of Zephyr's :ref:`lwm2m_interface` client. Overview ******** -The purpose of the library is to provide a basic combination of LwM2M objects, which forms a common communication framework for applications that communicate with an LwM2M server. +The purpose of the library is to provide a basic combination of LwM2M objects, which forms a common communication framework for applications that communicate with an LwM2M Server. Following are the fixed set of readily initialized objects that are available to the users: * Firmware Update object @@ -71,9 +71,6 @@ But if this waiting period is longer than the maximum delay set for the data tra .. note:: Connection pre-evaluation consumes a small amount of energy every time it requests information about a cell. -The :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_DTLS_CID` Kconfig option enables DTLS Connection Identifier functionality in handshake. -Enabling this feature requires that either the :kconfig:option:`CONFIG_LWM2M_RD_CLIENT_STOP_POLLING_AT_IDLE` or :kconfig:option:`CONFIG_LWM2M_RD_CLIENT_LISTEN_AT_IDLE` Kconfig option is selected. - Defining custom objects ======================= diff --git a/doc/nrf/libraries/networking/lwm2m_location_assistance.rst b/doc/nrf/libraries/networking/lwm2m_location_assistance.rst index 37513e1ddef..6c8730d7f08 100644 --- a/doc/nrf/libraries/networking/lwm2m_location_assistance.rst +++ b/doc/nrf/libraries/networking/lwm2m_location_assistance.rst @@ -7,14 +7,14 @@ LwM2M location assistance :local: :depth: 2 -The LwM2M location assistance library provides a proprietary mechanism to fetch location assistance data from `nRF Cloud`_ by proxying it through the LwM2M server. +The LwM2M location assistance library provides a proprietary mechanism to fetch location assistance data from `nRF Cloud`_ by proxying it through the LwM2M Server. Overview ******** Location Assistance object is a proprietary LwM2M object used to deliver information required by various location services through LwM2M. This feature is currently under development and considered :ref:`experimental `. -As of now, only AVSystem's Coiote LwM2M server can be used for utilizing the location assistance data from nRF Cloud. +As of now, only AVSystem's Coiote LwM2M Server can be used for utilizing the location assistance data from nRF Cloud. To know more about the AVSystem integration with |NCS|, see :ref:`ug_avsystem`. The library adds support for four objects related to location assistance: @@ -35,13 +35,13 @@ Supported features There are four different supported methods of obtaining the location assistance: -* Location based on cell information - The device sends information about the current cell and possibly about the neighboring cells to the LwM2M server. - The LwM2M server then sends the location request to nRF Cloud, which responds with the location data. -* Location based on Wi-Fi access points - The device sends information about the nearby Wi-Fi access points to the LwM2M server. - The LwM2M server then sends the location request to nRF Cloud, which responds with the location data. -* Query of A-GNSS assistance data - The A-GNSS assistance data is queried from nRF Cloud and provided back to the device through the LwM2M server. +* Location based on cell information - The device sends information about the current cell and possibly about the neighboring cells to the LwM2M Server. + The LwM2M Server then sends the location request to nRF Cloud, which responds with the location data. +* Location based on Wi-Fi access points - The device sends information about the nearby Wi-Fi access points to the LwM2M Server. + The LwM2M Server then sends the location request to nRF Cloud, which responds with the location data. +* Query of A-GNSS assistance data - The A-GNSS assistance data is queried from nRF Cloud and provided back to the device through the LwM2M Server. The A-GNSS assistance data is then provided to the GNSS module for obtaining the position fix faster. -* Query of P-GPS predictions - The P-GPS predictions are queried from nRF Cloud and provided back to the device through the LwM2M server. +* Query of P-GPS predictions - The P-GPS predictions are queried from nRF Cloud and provided back to the device through the LwM2M Server. The predictions are stored in the device flash and injected to the GNSS module when needed. API usage @@ -63,7 +63,7 @@ To populate the objects, call the :c:func:`lwm2m_ncell_handler_register` functio The Ground Fix Location object needs to address the ``report_back`` resource before sending a location request. Back reporting tells the server whether it needs to send the acquired location back to the device. -If the location is sent back to the device, the location is stored only in the Ground Fix Location object. +If the location is sent back to the device, the location is stored in the Ground Fix Location object and copied in the LwM2M Location object. To send the location request for the cell-based location, call the :c:func:`location_assistance_ground_fix_request_send` function. @@ -157,8 +157,8 @@ To enable location assistance, configure either or both of the following Kconfig Following are the other important library options: -* :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS` - nRF Cloud provides A-GNSS assistance data and the GNSS-module in the device uses the data for obtaining a GNSS fix, which is reported back to the LwM2M server. -* :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS` - nRF Cloud provides P-GPS predictions and the GNSS-module in the device uses the data for obtaining a GNSS fix, which is reported back to the LwM2M server. +* :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_AGNSS` - nRF Cloud provides A-GNSS assistance data and the GNSS-module in the device uses the data for obtaining a GNSS fix, which is reported back to the LwM2M Server. +* :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_PGPS` - nRF Cloud provides P-GPS predictions and the GNSS-module in the device uses the data for obtaining a GNSS fix, which is reported back to the LwM2M Server. * :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_CELL` - nRF Cloud provides estimated location based on currently attached cell and its neighborhood. * :kconfig:option:`CONFIG_LWM2M_CLIENT_UTILS_CONN_MON_OBJ_SUPPORT` - Enable support for connectivity monitoring utilities. Provides data about the current cell and network the device has connected to. diff --git a/doc/nrf/libraries/networking/mqtt_helper.rst b/doc/nrf/libraries/networking/mqtt_helper.rst index 8ea77301c99..e4ac0600074 100644 --- a/doc/nrf/libraries/networking/mqtt_helper.rst +++ b/doc/nrf/libraries/networking/mqtt_helper.rst @@ -27,7 +27,7 @@ Additionally, configure the following options as per the needs of your applicati * :kconfig:option:`CONFIG_MQTT_HELPER_RX_TX_BUFFER_SIZE` * :kconfig:option:`CONFIG_MQTT_HELPER_PAYLOAD_BUFFER_LEN` * :kconfig:option:`CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES` -* :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FILE` +* :kconfig:option:`CONFIG_MQTT_HELPER_CERTIFICATES_FOLDER` API documentation ***************** diff --git a/doc/nrf/libraries/networking/nrf_cloud.rst b/doc/nrf/libraries/networking/nrf_cloud.rst index c25d66b01bb..6ad22b81405 100644 --- a/doc/nrf/libraries/networking/nrf_cloud.rst +++ b/doc/nrf/libraries/networking/nrf_cloud.rst @@ -210,20 +210,6 @@ Sending sensor data ******************* The library offers two functions, :c:func:`nrf_cloud_sensor_data_send` and :c:func:`nrf_cloud_sensor_data_stream` (lowest QoS), for sending sensor data to the cloud. -To view sensor data on nRF Cloud, the device must first inform the cloud what types of sensor data to display. -The device passes this information by writing a ``ui`` field, containing an array of sensor types, into the ``serviceInfo`` field in the device's shadow. -The :c:func:`nrf_cloud_service_info_json_encode` function can be used to generate the proper JSON data to enable FOTA. -Additionally, the :c:func:`nrf_cloud_shadow_device_status_update` function can be used to generate the JSON data and perform the shadow update. - -Following are the supported UI types on nRF Cloud: - -* ``GNSS`` -* ``FLIP`` -* ``TEMP`` -* ``HUMIDITY`` -* ``AIR_PRESS`` -* ``RSRP`` - .. _lib_nrf_cloud_unlink: Removing the link between device and user @@ -274,3 +260,12 @@ nRF Cloud common definitions .. doxygengroup:: nrf_cloud_defs :project: nrf :members: + +nRF Cloud FOTA poll for REST and CoAP +**************************************** + +| Header file: :file:`include/net/nrf_cloud_fota_poll.h` + +.. doxygengroup:: nrf_cloud_fota_poll + :project: nrf + :members: diff --git a/doc/nrf/libraries/networking/nrf_cloud_coap.rst b/doc/nrf/libraries/networking/nrf_cloud_coap.rst index 18e15225748..e161ffb6ac9 100644 --- a/doc/nrf/libraries/networking/nrf_cloud_coap.rst +++ b/doc/nrf/libraries/networking/nrf_cloud_coap.rst @@ -52,7 +52,7 @@ Requirements You must first preprovision the device on nRF Cloud as follows: -1. Use the `device_credentials_installer.py`_ and `nrf_cloud_provision.py`_ scripts. +1. Use the `device_credentials_installer.py`_ and `nrf_cloud_onboard.py`_ scripts. #. Specify the ``--coap`` option to ``device_credentials_installer.py`` to have the proper root CA certificates installed in the device. Call the :c:func:`nrf_cloud_coap_init` function once to initialize the library. @@ -68,7 +68,6 @@ Additionally, the following Kconfig options are available: * :kconfig:option:`CONFIG_NRF_CLOUD_COAP_SERVER_HOSTNAME` * :kconfig:option:`CONFIG_NRF_CLOUD_COAP_SEC_TAG` * :kconfig:option:`CONFIG_NRF_CLOUD_COAP_RESPONSE_TIMEOUT_MS` -* :kconfig:option:`CONFIG_NON_RESP_RETRIES` * :kconfig:option:`CONFIG_NRF_CLOUD_COAP_SEND_SSIDS` * :kconfig:option:`CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS` * :kconfig:option:`CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_NETWORK` diff --git a/doc/nrf/libraries/networking/nrf_provisioning.rst b/doc/nrf/libraries/networking/nrf_provisioning.rst index 122f0f25e7b..7c6a209d117 100644 --- a/doc/nrf/libraries/networking/nrf_provisioning.rst +++ b/doc/nrf/libraries/networking/nrf_provisioning.rst @@ -156,10 +156,11 @@ The feature is enabled by selecting :kconfig:option:`CONFIG_NRF_PROVISIONING_SHE uart:~$ nrf_provisioning nrf_provisioning - nRF Provisioning commands Subcommands: - init :Start the client - now :Do provisioning now - token :Get the attestation token - uuid :Get device UUID + init: Start the client + now: Do provisioning now + token: Get the attestation token + uuid: Get device UUID + interval: Set provisioning interval Dependencies ************ diff --git a/doc/nrf/libraries/networking/wifi_credentials.rst b/doc/nrf/libraries/networking/wifi_credentials.rst index 257647bb0a6..d24e5ac80e1 100644 --- a/doc/nrf/libraries/networking/wifi_credentials.rst +++ b/doc/nrf/libraries/networking/wifi_credentials.rst @@ -12,7 +12,7 @@ The Wi-Fi credentials library provides means to load and store Wi-Fi network cre Overview ******** -This library uses either Zephyr's settings subsystem or Platform Security Architecture (PSA) protected storage to store credentials. +This library uses either Zephyr's settings subsystem or Platform Security Architecture (PSA) Internal Trusted Storage (ITS) to store credentials. It also holds a list of SSIDs in RAM to provide dictionary-like access using SSIDs as keys. Configuration @@ -30,7 +30,7 @@ To configure the maximum number of networks, use the :kconfig:option:`CONFIG_WIF The IEEE 802.11 standard does not specify the maximum length of SAE passwords. To change the default, use the :kconfig:option:`CONFIG_WIFI_CREDENTIALS_SAE_PASSWORD_LENGTH` Kconfig option. -When using the PSA protected storage backend, entries will be saved under consecutive UIDs with an offset configured with the :kconfig:option:`CONFIG_WIFI_CREDENTIALS_BACKEND_PSA_UID_OFFSET` Kconfig option. +When using the PSA ITS backend, entries will be saved under consecutive key IDs with an offset configured with the :kconfig:option:`CONFIG_WIFI_CREDENTIALS_BACKEND_PSA_OFFSET` Kconfig option. Adding credentials ****************** diff --git a/doc/nrf/libraries/nfc/ndef/msg_parser.rst b/doc/nrf/libraries/nfc/ndef/msg_parser.rst index 792bade954d..c871930f73a 100644 --- a/doc/nrf/libraries/nfc/ndef/msg_parser.rst +++ b/doc/nrf/libraries/nfc/ndef/msg_parser.rst @@ -7,7 +7,7 @@ Parser for messages and records :local: :depth: 2 -When using an NFC polling device, you can use the NDEF message parser module to interpret the NDEF messages the are read from the NFC tag. +When using an NFC polling device, you can use the NDEF message parser module to interpret the NDEF messages that are read from the NFC tag. See the documentation for the :ref:`nfc_t2t_parser_readme` for more information on how to read the content of the tag. This library can also be used together with the :ref:`nrfxlib:nfc_api_type4` in writable mode to parse the written NDEF message. diff --git a/doc/nrf/libraries/nrf_security/doc/configuration.rst b/doc/nrf/libraries/nrf_security/doc/configuration.rst deleted file mode 100644 index dc46b7351a4..00000000000 --- a/doc/nrf/libraries/nrf_security/doc/configuration.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. _nrf_security_config: - -Configuration -############# - -.. contents:: - :local: - :depth: 2 - -You can enable the nRF Security subsystem using `PSA crypto support`_ or `Legacy crypto support`_. - -To enable nRF Security, set the :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig option along with additional configuration options, as described in :ref:`nrf_security_driver_config`. -This includes PSA crypto support by default. - -PSA crypto support -****************** - -PSA crypto support is included by default when you enable nRF Security through the :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig option. -PSA crypto support is provided through PSA Crypto APIs and is implemented by PSA core. -PSA core uses PSA drivers to implement the cryptographic features either in software, or using hardware accelerators. - -.. _legacy_crypto_support: - -Legacy crypto support -********************* - -To enable the legacy crypto support mode of nRF Security, set both the :kconfig:option:`CONFIG_NORDIC_SECURITY_BACKEND` and :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig options along with additional configuration options, as described in :ref:`nrf_security_legacy_config`. -The legacy crypto support allows backwards compatibility for software that requires usage of Mbed TLS crypto toolbox functions prefixed with ``mbedtls_``. - -Custom Mbed TLS configuration files -*********************************** - -The nRF Security Kconfig options are used to generate an Mbed TLS configuration file. - -Although not recommended, it is possible to provide a custom Mbed TLS configuration file by disabling :kconfig:option:`CONFIG_GENERATE_MBEDTLS_CFG_FILE`. -See :ref:`nrf_security_tls_header`. - -Building with TF-M -****************** - -If :kconfig:option:`CONFIG_BUILD_WITH_TFM` is enabled together with :kconfig:option:`CONFIG_NRF_SECURITY`, the TF-M secure image will enable the use of the hardware acceleration of Arm CryptoCell. -In this case, the Kconfig configurations in the nRF Security subsystem control the features enabled in TF-M. diff --git a/doc/nrf/libraries/others/app_event_manager.rst b/doc/nrf/libraries/others/app_event_manager.rst index 4a5f73a13f0..967cc03fd6c 100644 --- a/doc/nrf/libraries/others/app_event_manager.rst +++ b/doc/nrf/libraries/others/app_event_manager.rst @@ -141,7 +141,7 @@ To create a source file for the event type you defined in the header file: 1. Include the header file for the new event type in your source file. #. Define the event type with the :c:macro:`APP_EVENT_TYPE_DEFINE` macro. Pass the name of the event type as declared in the header along with additional parameters. - For example, you can provide a function that logs a string version of the event data by using the :c:macro:APP_EVENT_MANAGER_LOG macro. + For example, you can provide a function that logs a string version of the event data by using the :c:macro:`APP_EVENT_MANAGER_LOG` macro. The :c:macro:`APP_EVENT_TYPE_DEFINE` macro adds flags as a last parameter. These flags are constant and can only be set using :c:macro:`APP_EVENT_FLAGS_CREATE` on :c:macro:`APP_EVENT_TYPE_DEFINE` macro. To not set any flag, use the :c:macro:`APP_EVENT_FLAGS_CREATE` macro without any argument. diff --git a/doc/nrf/libraries/others/date_time.rst b/doc/nrf/libraries/others/date_time.rst index c92a2f5673e..fa3ed99f394 100644 --- a/doc/nrf/libraries/others/date_time.rst +++ b/doc/nrf/libraries/others/date_time.rst @@ -50,7 +50,7 @@ See the API documentation for more information on these functions. .. note:: It is recommended to set the :kconfig:option:`CONFIG_DATE_TIME_AUTO_UPDATE` option to trigger a time update when the device has connected to LTE. - If an application has time-dependent operations immediately after connecting to LTE network, it should wait for a confirmation telling that time has been updated. + If an application has time-dependent operations immediately after connecting to the LTE network, it should wait for a confirmation indicating that time has been updated. If the :kconfig:option:`CONFIG_DATE_TIME_AUTO_UPDATE` option is not set, the first date-time update cycle (after boot) does not occur until the time set by the :kconfig:option:`CONFIG_DATE_TIME_UPDATE_INTERVAL_SECONDS` option has elapsed. Configuration diff --git a/doc/nrf/libraries/others/uart_async_adapter.rst b/doc/nrf/libraries/others/uart_async_adapter.rst new file mode 100644 index 00000000000..30d30f93afd --- /dev/null +++ b/doc/nrf/libraries/others/uart_async_adapter.rst @@ -0,0 +1,102 @@ +.. _lib_uart_async_adapter: + +UART async adapter +################## + +.. contents:: + :local: + :depth: 2 + +UART async adapter library works as an interface between interrupt-driven API of a UART device and software that is using the asynchronous API interface. + +.. note:: + The current implementation is :ref:`experimental `. + +Overview +******** + +Zephyr provides the following three different ways to access a UART peripheral: + +* Pooling API +* Interrupt-driven API +* Asynchronous API + +While most of the UART drivers provide all three APIs, some drivers still do not provide the asynchronous UART API. +An example of such a driver is USB CDC ACM. +The UART async adapter library is initialized with a UART device and communicates with it using the interrupt-driven API, providing an asynchronous API for the application. + +This removes the need to implement two ways of interfacing with UART devices in software. +When using the UART async adapter library, the software only needs to implement interaction with a UART device using the asynchronous API and just initialize the adapter for the ones that do not support it. + +Requirements +************ + +To use the library, you need to enable the :kconfig:option:`CONFIG_UART_ASYNC_API` and :kconfig:option:`CONFIG_UART_INTERRUPT_DRIVEN` Kconfig options. + +Configuration +************* + +Use the :kconfig:option:`CONFIG_UART_ASYNC_ADAPTER` Kconfig option to enable the library in the build system. + +Usage +***** + +See the following code snippet to learn how to use this library: + +.. code-block:: c + + #include + + ... + /* Get the UART device we want to use */ + static const struct device *uart = DEVICE_DT_GET([UART node identifier]); + + /* Create UART async adapter instance */ + UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter); + + /* UART initialization (called before any UART usage) */ + static int uart_init(void) + { + if (!uart_test_async_api(uart)) { + /* Implement API adapter */ + uart_async_adapter_init(async_adapter, uart); + uart = async_adapter; + } + /* Continue initialization using asynchronous API on uart device */ + (...) + } + +.. note:: + When using the library in the way shown in the code snippet, it is totally transparent to the application. + +If the selected UART device provides the asynchronous API, the adapter is not initialized. +If the selected UART device does not provide the asynchronous API, the adapter is initialized to use such a device and a direct pointer to the device is replaced by the adapter. + +Samples using the library +************************* + +The following |NCS| sample use this library: + +* :ref:`peripheral_uart` + +Limitations +*********** + +Using this library adds code and performance overhead over direct usage of UART asynchronous API provided by the driver. +For UART drivers that only provide the interrupt-driven API, consider using it directly in the application. +The library allows using UART devices with different APIs with only one API in the application, speeding up the development process. + +Dependencies +************ + +This module may use :ref:`zephyr:logging_api`. + +API documentation +***************** + +| Header file: :file:`include/uart_async_adapter.h` +| Source files: :file:`subsys/uart_async_adapter/` + +.. doxygengroup:: uart_async_adapter + :project: nrf + :members: diff --git a/doc/nrf/libraries/bootloader/bl_crypto.rst b/doc/nrf/libraries/security/bootloader/bl_crypto.rst similarity index 100% rename from doc/nrf/libraries/bootloader/bl_crypto.rst rename to doc/nrf/libraries/security/bootloader/bl_crypto.rst diff --git a/doc/nrf/libraries/bootloader/bl_storage.rst b/doc/nrf/libraries/security/bootloader/bl_storage.rst similarity index 100% rename from doc/nrf/libraries/bootloader/bl_storage.rst rename to doc/nrf/libraries/security/bootloader/bl_storage.rst diff --git a/doc/nrf/libraries/bootloader/bl_validation.rst b/doc/nrf/libraries/security/bootloader/bl_validation.rst similarity index 100% rename from doc/nrf/libraries/bootloader/bl_validation.rst rename to doc/nrf/libraries/security/bootloader/bl_validation.rst diff --git a/doc/nrf/libraries/others/flash_patch.rst b/doc/nrf/libraries/security/bootloader/flash_patch.rst similarity index 100% rename from doc/nrf/libraries/others/flash_patch.rst rename to doc/nrf/libraries/security/bootloader/flash_patch.rst diff --git a/doc/nrf/libraries/others/fprotect.rst b/doc/nrf/libraries/security/bootloader/fprotect.rst similarity index 100% rename from doc/nrf/libraries/others/fprotect.rst rename to doc/nrf/libraries/security/bootloader/fprotect.rst diff --git a/doc/nrf/libraries/others/fw_info.rst b/doc/nrf/libraries/security/bootloader/fw_info.rst similarity index 100% rename from doc/nrf/libraries/others/fw_info.rst rename to doc/nrf/libraries/security/bootloader/fw_info.rst diff --git a/doc/nrf/libraries/bootloader/index.rst b/doc/nrf/libraries/security/bootloader/index.rst similarity index 100% rename from doc/nrf/libraries/bootloader/index.rst rename to doc/nrf/libraries/security/bootloader/index.rst diff --git a/doc/nrf/libraries/others/fatal_error.rst b/doc/nrf/libraries/security/fatal_error.rst similarity index 100% rename from doc/nrf/libraries/others/fatal_error.rst rename to doc/nrf/libraries/security/fatal_error.rst diff --git a/doc/nrf/libraries/others/hw_unique_key.rst b/doc/nrf/libraries/security/hw_unique_key.rst similarity index 100% rename from doc/nrf/libraries/others/hw_unique_key.rst rename to doc/nrf/libraries/security/hw_unique_key.rst diff --git a/doc/nrf/libraries/others/identity_key.rst b/doc/nrf/libraries/security/identity_key.rst similarity index 100% rename from doc/nrf/libraries/others/identity_key.rst rename to doc/nrf/libraries/security/identity_key.rst diff --git a/doc/nrf/libraries/security/images/trusted_storage.svg b/doc/nrf/libraries/security/images/trusted_storage.svg new file mode 100644 index 00000000000..f19417b5738 --- /dev/null +++ b/doc/nrf/libraries/security/images/trusted_storage.svg @@ -0,0 +1,1711 @@ + + + + + + + + + + + + + + + + + + + Page-1 + + Dynamic connector.117 + + + + Dynamic connector + + + + Sheet.18 + NONCE + + NONCE + + Dynamic connector.29 + + + + Sheet.25 + TRUSTED_STORAGE_BACKEND_AEAD + + TRUSTED_STORAGE_BACKEND_AEAD + + Dynamic connector.32 + + + + Folded Corner.36 + + + + + Sheet.30 + + + + + Sheet.31 + Encrypted asset + + Encrypted asset + + Decision + Authentication tag + + Authentication tag + + Sheet.34 + TRUSTED_STORAGE_STORAGE_BACKEND + + TRUSTED_STORAGE_STORAGE_BACKEND + + Can + NVM storage + + Sheet.37 + + + + + NVM storage + + + Dynamic connector.97 + + + + Folded Corner.52 + + + + + Sheet.53 + + + + + Sheet.54 + Encrypted asset + + Encrypted asset + + Decision.55 + Authentication tag + + Authentication tag + + Folded Corner.59 + + + + + Sheet.60 + + + + + Sheet.61 + Encrypted asset + + Encrypted asset + + Decision.62 + Authentication tag + + Authentication tag + + Dynamic connector.110 + + + + Dynamic connector.111 + + + + Dynamic connector.112 + + + + Nordic Fall + Application + + Application + + Nordic Sun + PSA Protected Storage API + + PSA Protected Storage API + + Nordic Sun.118 + PSA Internal Trusted Storage API + + PSA Internal Trusted Storage API + + Dynamic connector.168 + + + + Nordic Grass + + + + Nordic Grass.170 + + + + Sheet.171 + HUK library + + HUK library + + Nordic Grass.172 + CRYPTO_PSA_CHACHAPOLY + + CRYPTO_PSA_CHACHAPOLY + + Nordic Grass.173 + KEY_DERIVE_FROM_HUK + + KEY_DERIVE_FROM_HUK + + Nordic Grass.174 + NONCE_PSA_SEED_COUNTER + + NONCE_PSA_SEED_COUNTER + + Dynamic connector.271 + + + + Dynamic connector.272 + + + + Dynamic connector.275 + + + + Dynamic connector.276 + + + + Nordic Sky + TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS + + TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS + + Sheet.26 + TRUSTED_STORAGE_BACKEND + + TRUSTED_STORAGE_BACKEND + + Nordic Sky.279 + Settings + + Settings + + Dynamic connector.280 + + + + Sheet.175 + + + + + + Sheet.176 + + + + + + Folded Corner + + + + + Sheet.20 + + + + + Sheet.21 + Asset + + Asset + + diff --git a/doc/nrf/libraries/security/index.rst b/doc/nrf/libraries/security/index.rst new file mode 100644 index 00000000000..0b7285b194c --- /dev/null +++ b/doc/nrf/libraries/security/index.rst @@ -0,0 +1,14 @@ +.. _lib_security: + +Security libraries +################## + +.. toctree:: + :maxdepth: 1 + :glob: + :caption: Subpages: + + bootloader/index + nrf_security/index + tfm/index + * diff --git a/doc/nrf/libraries/nrf_security/doc/backend_config.rst b/doc/nrf/libraries/security/nrf_security/doc/backend_config.rst similarity index 100% rename from doc/nrf/libraries/nrf_security/doc/backend_config.rst rename to doc/nrf/libraries/security/nrf_security/doc/backend_config.rst diff --git a/doc/nrf/libraries/security/nrf_security/doc/configuration.rst b/doc/nrf/libraries/security/nrf_security/doc/configuration.rst new file mode 100644 index 00000000000..10065333697 --- /dev/null +++ b/doc/nrf/libraries/security/nrf_security/doc/configuration.rst @@ -0,0 +1,45 @@ +.. _nrf_security_config: + +Configuration +############# + +.. contents:: + :local: + :depth: 2 + +You can enable the nRF Security subsystem using `PSA crypto support`_ or `Legacy crypto support`_. + +To enable nRF Security, set the :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig option along with additional configuration options, as described in :ref:`nrf_security_driver_config`. +This includes PSA crypto support by default. + +PSA crypto support +****************** + +PSA crypto support is included by default when you enable nRF Security through the :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig option. +PSA crypto support is provided through PSA Crypto APIs and is implemented by PSA core. +PSA core uses PSA drivers to implement the cryptographic features either in software, or using hardware accelerators. + +.. caution:: + The PSA Crypto APIs are only thread safe when provided by TF-M. + +.. _legacy_crypto_support: + +Legacy crypto support +********************* + +To enable the legacy crypto support mode of nRF Security, set both the :kconfig:option:`CONFIG_NORDIC_SECURITY_BACKEND` and :kconfig:option:`CONFIG_NRF_SECURITY` Kconfig options along with additional configuration options, as described in :ref:`nrf_security_legacy_config`. +The legacy crypto support allows backwards compatibility for software that requires usage of Mbed TLS crypto toolbox functions prefixed with ``mbedtls_``. + +Custom Mbed TLS configuration files +*********************************** + +The nRF Security Kconfig options are used to generate an Mbed TLS configuration file. + +Although not recommended, it is possible to provide a custom Mbed TLS configuration file by disabling :kconfig:option:`CONFIG_GENERATE_MBEDTLS_CFG_FILE`. +See :ref:`nrf_security_tls_header`. + +Building with TF-M +****************** + +If :kconfig:option:`CONFIG_BUILD_WITH_TFM` is enabled together with :kconfig:option:`CONFIG_NRF_SECURITY`, the TF-M secure image will enable the use of the hardware acceleration of Arm CryptoCell. +In this case, the Kconfig configurations in the nRF Security subsystem control the features enabled in TF-M. diff --git a/doc/nrf/libraries/nrf_security/doc/driver_config.rst b/doc/nrf/libraries/security/nrf_security/doc/driver_config.rst similarity index 77% rename from doc/nrf/libraries/nrf_security/doc/driver_config.rst rename to doc/nrf/libraries/security/nrf_security/doc/driver_config.rst index 9263e1ad025..9dbbcbdc19e 100644 --- a/doc/nrf/libraries/nrf_security/doc/driver_config.rst +++ b/doc/nrf/libraries/security/nrf_security/doc/driver_config.rst @@ -25,6 +25,8 @@ To enable a PSA driver, set the configurations in the following table: +---------------+--------------------------------------------------+-----------------------------------------------------+ | nrf_oberon | :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_OBERON`| | +---------------+--------------------------------------------------+-----------------------------------------------------+ +| nrf_cracen | :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_CRACEN`| Only on nRF54L Series devices | ++---------------+--------------------------------------------------+-----------------------------------------------------+ If multiple drivers are enabled, the first ordered item in this table takes precedence for an enabled cryptographic feature, unless the driver does not enable or support it. @@ -74,35 +76,35 @@ Key type support The following table shows key type support for each driver: -+-----------------------+---------------------------+----------------------------+ -| Key type | nrf_cc3xx driver support | nrf_oberon driver support | -+=======================+===========================+============================+ -| AES | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| ARIA | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| DES (weak) | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| CAMELLIA | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| SM4 | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| ARC4 (weak) | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| Chacha20 | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| ECC Key Pair | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| ECC Public Key | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| RSA Key Pair | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| RSA Public Key | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| DH Key Pair | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| DH Public Key | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ ++-----------------------+---------------------------+----------------------------+---------------------------+ +| Key type | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=======================+===========================+============================+===========================+ +| AES | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| ARIA | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| DES (weak) | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CAMELLIA | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| SM4 | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| ARC4 (weak) | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| Chacha20 | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| ECC Key Pair | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| ECC Public Key | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| RSA Key Pair | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| RSA Public Key | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| DH Key Pair | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| DH Public Key | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_KEY_MANAGEMENT_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported key types. @@ -138,27 +140,27 @@ Cipher support The following table shows cipher algorithm support for each driver: -+-----------------------+---------------------------+----------------------------+ -| Cipher mode | nrf_cc3xx driver support | nrf_oberon driver support | -+=======================+===========================+============================+ -| ECB no padding | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| CBC no padding | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| CBC PKCS#7 padding | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| CFB | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| CTR | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| OFB | Supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| CCM* no tag | Not supported | Supported | -+-----------------------+---------------------------+----------------------------+ -| XTS | Not supported | Not supported | -+-----------------------+---------------------------+----------------------------+ -| Stream cipher | Supported | Supported | -+-----------------------+---------------------------+----------------------------+ ++-----------------------+---------------------------+----------------------------+---------------------------+ +| Cipher mode | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=======================+===========================+============================+===========================+ +| ECB no padding | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CBC no padding | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CBC PKCS#7 padding | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CFB | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CTR | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| OFB | Supported | Not supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| CCM* no tag | Not supported | Supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| XTS | Not supported | Not supported | Not supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ +| Stream cipher | Supported | Supported | Supported | ++-----------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_CIPHER_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -187,13 +189,13 @@ Key agreement support The following table shows Key agreement support for each driver: -+-------------------------+---------------------------+----------------------------+ -| Key agreement algorithm | nrf_cc3xx driver support | nrf_oberon driver support | -+=========================+===========================+============================+ -| ECDH | Supported | Supported | -+-------------------------+---------------------------+----------------------------+ -| FFDH | Not supported | Not supported | -+-------------------------+---------------------------+----------------------------+ ++-------------------------+---------------------------+----------------------------+---------------------------+ +| Key agreement algorithm | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=========================+===========================+============================+===========================+ +| ECDH | Supported | Supported | Supported | ++-------------------------+---------------------------+----------------------------+---------------------------+ +| FFDH | Not supported | Not supported | Not supported | ++-------------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_KEY_AGREEMENT_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -235,25 +237,25 @@ Key derivation function support The following table shows key derivation function (KDF) support for each driver: -+--------------------------+--------------------------+----------------------------+ -| KDF algorithm | nrf_cc3xx driver support | nrf_oberon driver support | -+==========================+==========================+============================+ -| HKDF | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| HKDF-Extract | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| HKDF-Expand | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| PBKDF2-HMAC | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| PBKDF2-AES-CMAC-PRF-128 | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| TLS 1.2 PRF | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| TLS 1.2 PSK to MS | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ -| TLS 1.2 EC J-PAKE to PMS | Not supported | Supported | -+--------------------------+--------------------------+----------------------------+ ++--------------------------+--------------------------+----------------------------+---------------------------+ +| KDF algorithm | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++==========================+==========================+============================+===========================+ +| HKDF | Not supported | Supported | Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| HKDF-Extract | Not supported | Supported | Not Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| HKDF-Expand | Not supported | Supported | Not Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| PBKDF2-HMAC | Not supported | Supported | Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| PBKDF2-AES-CMAC-PRF-128 | Not supported | Supported | Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| TLS 1.2 PRF | Not supported | Supported | Not Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| TLS 1.2 PSK to MS | Not supported | Supported | Not Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ +| TLS 1.2 EC J-PAKE to PMS | Not supported | Supported | Supported | ++--------------------------+--------------------------+----------------------------+---------------------------+ The configuration of the :ref:`nrf_security_drivers_oberon` is automatically generated based on the user-enabled algorithms in `Key derivation function configurations`_. @@ -277,15 +279,15 @@ MAC support The following table shows MAC algorithm support for each driver: -+----------------+--------------------------+----------------------------+ -| MAC cipher | nrf_cc3xx driver support | nrf_oberon driver support | -+================+==========================+============================+ -| CMAC | Supported | Supported | -+----------------+--------------------------+----------------------------+ -| HMAC | Supported | Supported | -+----------------+--------------------------+----------------------------+ -| CBC-MAC | Not supported | Not supported | -+----------------+--------------------------+----------------------------+ ++----------------+--------------------------+----------------------------+---------------------------+ +| MAC cipher | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++================+==========================+============================+===========================+ +| CMAC | Supported | Supported | Supported | ++----------------+--------------------------+----------------------------+---------------------------+ +| HMAC | Supported | Supported | Supported | ++----------------+--------------------------+----------------------------+---------------------------+ +| CBC-MAC | Not supported | Not supported | Not Supported | ++----------------+--------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_MAC_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -317,15 +319,15 @@ AEAD support The following table shows AEAD algorithm support for each driver: -+-----------------------+---------------------------+---------------------------+ -| AEAD cipher | nrf_cc3xx driver support | nrf_oberon driver support | -+=======================+===========================+===========================+ -| CCM | Supported | Supported | -+-----------------------+---------------------------+---------------------------+ -| GCM | Supported | Supported | -+-----------------------+---------------------------+---------------------------+ -| ChaCha20-Poly1305 | Supported | Supported | -+-----------------------+---------------------------+---------------------------+ ++-----------------------+---------------------------+---------------------------+---------------------------+ +| AEAD cipher | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=======================+===========================+===========================+===========================+ +| CCM | Supported | Supported | Supported | ++-----------------------+---------------------------+---------------------------+---------------------------+ +| GCM | Supported | Supported | Supported | ++-----------------------+---------------------------+---------------------------+---------------------------+ +| ChaCha20-Poly1305 | Supported | Supported | Supported | ++-----------------------+---------------------------+---------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_AEAD_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -372,29 +374,29 @@ Asymmetric signature support The following table shows asymmetric signature algorithm support for each driver: -+---------------------------------+---------------------------+----------------------------+ -| Asymmetric signature algorithms | nrf_cc3xx driver support | nrf_oberon driver support | -+=================================+===========================+============================+ -| ECDSA | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| ECDSA without hashing | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| ECDSA (deterministic) | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| PureEdDSA | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| HashEdDSA Edwards25519 | Not supported | Not supported | -+---------------------------------+---------------------------+----------------------------+ -| HashEdDSA Edwards448 | Not supported | Not supported | -+---------------------------------+---------------------------+----------------------------+ -| RSA PKCS#1 v1.5 sign | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| RSA raw PKCS#1 v1.5 sign | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| RSA PSS | Not supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| RSA PSS any salt | Not supported | Supported | -+---------------------------------+---------------------------+----------------------------+ ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| Asymmetric signature algorithms | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=================================+===========================+============================+===========================+ +| ECDSA | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| ECDSA without hashing | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| ECDSA (deterministic) | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| PureEdDSA | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| HashEdDSA Edwards25519 | Not supported | Not supported | Not supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| HashEdDSA Edwards448 | Not supported | Not supported | Not supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| RSA PKCS#1 v1.5 sign | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| RSA raw PKCS#1 v1.5 sign | Supported | Supported | Not Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| RSA PSS | Not supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| RSA PSS any salt | Not supported | Supported | Not Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_ASYMMETRIC_SIGNATURE_DRIVER` enables the driver :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -428,13 +430,13 @@ Asymmetric encryption support The following table shows asymmetric encryption algorithm support for each driver: -+---------------------------------+---------------------------+----------------------------+ -| Asymmetric encryption algorithm | nrf_cc3xx driver support | nrf_oberon driver support | -+=================================+===========================+============================+ -| RSA OAEP | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ -| RSA PKCS#1 v1.5 crypt | Supported | Supported | -+---------------------------------+---------------------------+----------------------------+ ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| Asymmetric encryption algorithm | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=================================+===========================+============================+===========================+ +| RSA OAEP | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ +| RSA PKCS#1 v1.5 crypt | Supported | Supported | Supported | ++---------------------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_ASYMMETRIC_ENCRYPTION_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -526,75 +528,75 @@ ECC curve support The following table shows ECC curve support for each driver: -+--------------------------+---------------------------+----------------------------+ -| ECC curve type | nrf_cc3xx driver support | nrf_oberon driver support | -+==========================+===========================+============================+ -| BrainpoolP160r1 (weak) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP192r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP224r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP256r1 | Supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP320r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP384r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| BrainpoolP512r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| Curve25519 (X25519) | Supported | Supported | -+--------------------------+---------------------------+----------------------------+ -| Curve448 (X448) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| Edwards25519 (Ed25519) | Supported | Supported | -+--------------------------+---------------------------+----------------------------+ -| Edwards448 (Ed448) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp192k1 | Supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp224k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp256k1 | Supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp192r1 | Supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp224r1 | Supported | Supported | -+--------------------------+---------------------------+----------------------------+ -| secp256r1 | Supported | Supported | -+--------------------------+---------------------------+----------------------------+ -| secp384r1 | Supported | Supported | -+--------------------------+---------------------------+----------------------------+ -| secp521r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| secp160r2 (weak) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect163k1 (weak) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect233k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect239k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect283k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect409k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect571k1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect163r1 (weak) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect233r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect283r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect409r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect571r1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| sect163r2 (weak) | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ -| FRP256v1 | Not supported | Not supported | -+--------------------------+---------------------------+----------------------------+ ++--------------------------+---------------------------+----------------------------+---------------------------+ +| ECC curve type | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++==========================+===========================+============================+===========================+ +| BrainpoolP160r1 (weak) | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP192r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP224r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP256r1 | Supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP320r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP384r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| BrainpoolP512r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| Curve25519 (X25519) | Supported | Supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| Curve448 (X448) | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| Edwards25519 (Ed25519) | Supported | Supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| Edwards448 (Ed448) | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp192k1 | Supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp224k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp256k1 | Supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp192r1 | Supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp224r1 | Supported | Supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp256r1 | Supported | Supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp384r1 | Supported | Supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp521r1 | Not supported | Not supported | Supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| secp160r2 (weak) | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect163k1 (weak) | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect233k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect239k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect283k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect409k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect571k1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect163r1 (weak) | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect233r1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect283r1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect409r1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect571r1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| sect163r2 (weak) | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ +| FRP256v1 | Not supported | Not supported | Not supported | ++--------------------------+---------------------------+----------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_KEY_MANAGEMENT_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for key management using ECC curves. @@ -628,6 +630,9 @@ The PSA drivers using the Arm CryptoCell peripheral is enabled by default for nR For devices without a hardware-accelerated cryptographic engine, entropy is provided by the nRF RNG peripheral. PRNG support is provided by the Oberon PSA driver, which is implemented using software. +.. note:: + * When using CryptoCell only 1024 bytes can be requested at a time. + Hash configurations ******************* @@ -680,43 +685,43 @@ Hash support The following table shows hash algorithm support for each driver: -+-----------------------+----------------------------+---------------------------+ -| Hash algorithm | nrf_cc3xx driver support | nrf_oberon driver support | -+=======================+============================+===========================+ -| SHA-1 (weak) | Supported | Supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-224 | Supported | Supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-256 | Supported | Supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-384 | Not supported | Supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-512 | Not supported | Supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-512/224 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHA-512/256 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHA3-224 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHA3-256 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHA3-384 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHA3-512 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SM3 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| SHAKE256 512 bits | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| MD2 (weak) | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| MD4 (weak) | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| MD5 (weak) | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ -| RIPEMD160 | Not supported | Not supported | -+-----------------------+----------------------------+---------------------------+ ++-----------------------+----------------------------+---------------------------+---------------------------+ +| Hash algorithm | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=======================+============================+===========================+===========================+ +| SHA-1 (weak) | Supported | Supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-224 | Supported | Supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-256 | Supported | Supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-384 | Not supported | Supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-512 | Not supported | Supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-512/224 | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA-512/256 | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA3-224 | Not supported | Not supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA3-256 | Not supported | Not supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA3-384 | Not supported | Not supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHA3-512 | Not supported | Not supported | Supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SM3 | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| SHAKE256 512 bits | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| MD2 (weak) | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| MD4 (weak) | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| MD5 (weak) | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ +| RIPEMD160 | Not supported | Not supported | Not supported | ++-----------------------+----------------------------+---------------------------+---------------------------+ The option :kconfig:option:`CONFIG_PSA_USE_CC3XX_HASH_DRIVER` enables the :ref:`nrf_security_drivers_cc3xx` for all supported algorithms. @@ -727,34 +732,39 @@ Password-authenticated key exchange configurations To enable password-authenticated key exchange (PAKE) support, set one or more of the Kconfig options in the following table: -+-----------------------+-----------------------------------------------+ -| PAKE algorithm | Configuration option | -+=======================+===============================================+ -| EC J-PAKE | :kconfig:option:`CONFIG_PSA_WANT_ALG_JPAKE` | -+-----------------------+-----------------------------------------------+ -| SPAKE2+ | :kconfig:option:`CONFIG_PSA_WANT_ALG_SPAKE2P` | -+-----------------------+-----------------------------------------------+ -| SRP-6 | :kconfig:option:`CONFIG_PSA_WANT_ALG_SRP_6` | -+-----------------------+-----------------------------------------------+ ++------------------------+------------------------------------------------------+ +| PAKE algorithm | Configuration option | ++========================+======================================================+ +| EC J-PAKE | :kconfig:option:`CONFIG_PSA_WANT_ALG_JPAKE` | ++------------------------+------------------------------------------------------+ +| SPAKE2+ with HMAC | :kconfig:option:`CONFIG_PSA_WANT_ALG_SPAKE2P_HMAC` | ++------------------------+------------------------------------------------------+ +| SPAKE2+ with CMAC | :kconfig:option:`CONFIG_PSA_WANT_ALG_SPAKE2P_CMAC` | ++------------------------+------------------------------------------------------+ +| SPAKE2+ for Matter | :kconfig:option:`CONFIG_PSA_WANT_ALG_SPAKE2P_MATTER` | ++------------------------+------------------------------------------------------+ +| SRP-6 | :kconfig:option:`CONFIG_PSA_WANT_ALG_SRP_6` | ++------------------------+------------------------------------------------------+ +| SRP-6 password hashing | :kconfig:option:`CONFIG_PSA_WANT_ALG_SRP_6` | ++------------------------+------------------------------------------------------+ .. note:: * The provided support is experimental. - * Not supported with TF-M. Password-authenticated key exchange support =========================================== The following table shows PAKE algorithm support for each driver: -+-----------------------+--------------------------+---------------------------+ -| PAKE algorithm | nrf_cc3xx driver support | nrf_oberon driver support | -+=======================+==========================+===========================+ -| EC J-PAKE | Not supported | Supported | -+-----------------------+--------------------------+---------------------------+ -| SPAKE2+ | Not supported | Supported | -+-----------------------+--------------------------+---------------------------+ -| SRP-6 | Not supported | Supported | -+-----------------------+--------------------------+---------------------------+ ++-----------------------+--------------------------+---------------------------+---------------------------+ +| PAKE algorithm | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++=======================+==========================+===========================+===========================+ +| EC J-PAKE | Not supported | Supported | Supported | ++-----------------------+--------------------------+---------------------------+---------------------------+ +| SPAKE2+ | Not supported | Supported | Supported | ++-----------------------+--------------------------+---------------------------+---------------------------+ +| SRP-6 | Not supported | Supported | Supported | ++-----------------------+--------------------------+---------------------------+---------------------------+ Configuration of the :ref:`nrf_security_drivers_oberon` is automatically generated based on the user-enabled algorithms in `Password-authenticated key exchange configurations`_. @@ -786,23 +796,23 @@ RSA key size configuration To enable RSA key size support, set one or more of the Kconfig options in the following table: -+--------------------+-----------------------------------------------------+ -| RSA key size | Configuration option | -+====================+=====================================================+ -| 1024 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1024` | -+--------------------+-----------------------------------------------------+ -| 1536 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1536` | -+--------------------+-----------------------------------------------------+ -| 2048 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_2048` | -+--------------------+-----------------------------------------------------+ -| 3072 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_3072` | -+--------------------+-----------------------------------------------------+ -| 4096 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_4096` | -+--------------------+-----------------------------------------------------+ -| 6144 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_6144` | -+--------------------+-----------------------------------------------------+ -| 8192 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_8192` | -+--------------------+-----------------------------------------------------+ ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| RSA key size | Configuration option | nrf_cc3xx driver support | nrf_oberon driver support | nrf_cracen driver support | ++====================+=====================================================+==========================+===========================+===========================+ +| 1024 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1024` | Supported | Supported | Not supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 1536 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1536` | Supported | Supported | Not supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 2048 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_2048` | Supported | Supported | Supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 3072 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_3072` | Supported (CC312 only) | Supported | Supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 4096 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_4096` | Not supported | Supported | Supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 6144 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_6144` | Not supported | Supported | Not supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ +| 8192 bits | :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_8192` | Not supported | Supported | Not supported | ++--------------------+-----------------------------------------------------+--------------------------+---------------------------+---------------------------+ .. note:: All RSA key size configurations are introduced by :ref:`nrf_security` and are not described by the PSA Crypto specification. diff --git a/doc/nrf/libraries/nrf_security/doc/drivers.rst b/doc/nrf/libraries/security/nrf_security/doc/drivers.rst similarity index 82% rename from doc/nrf/libraries/nrf_security/doc/drivers.rst rename to doc/nrf/libraries/security/nrf_security/doc/drivers.rst index 7bf40290af1..42d9d59cc0c 100644 --- a/doc/nrf/libraries/nrf_security/doc/drivers.rst +++ b/doc/nrf/libraries/security/nrf_security/doc/drivers.rst @@ -20,6 +20,7 @@ The nRF Security supports the following PSA drivers: * Arm CryptoCell cc3xx binary * nrf_oberon binary +* CRACEN sources .. note:: Whenever this documentation mentions 'original' Mbed TLS, it refers to the open-source `Arm Mbed TLS project`_, not the customized version available in Zephyr. @@ -77,6 +78,25 @@ Enabling the nrf_oberon driver To enable the :ref:`nrf_oberon_readme` PSA driver, set the :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_OBERON` Kconfig option. +.. _nrf_security_drivers_cracen: + +CRACEN driver +************* + +The CRACEN driver provides entropy and hardware-accelerated cryptography using the CRACEN (Crypto Accelerator Engine) peripheral. +This driver is only available on nRF54L Series devices. + +Enabling the CRACEN driver +========================== + +The CRACEN driver can be enabled by setting the :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_CRACEN` Kconfig option. + +The nrf_oberon driver may then be disabled by using the Kconfig option :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_OBERON` (``CONFIG_PSA_CRYPTO_DRIVER_OBERON=n``). + +.. note:: + On nRF54L Series devices, CRACEN is the only source of entropy. + Therefore, it is not possible to disable the :kconfig:option:`CONFIG_PSA_CRYPTO_DRIVER_CRACEN` option when the Zephyr entropy driver is enabled. + Legacy Mbed TLS *************** diff --git a/doc/nrf/libraries/nrf_security/doc/mbed_tls_header.rst b/doc/nrf/libraries/security/nrf_security/doc/mbed_tls_header.rst similarity index 94% rename from doc/nrf/libraries/nrf_security/doc/mbed_tls_header.rst rename to doc/nrf/libraries/security/nrf_security/doc/mbed_tls_header.rst index afd7250c096..13f1f59973a 100644 --- a/doc/nrf/libraries/nrf_security/doc/mbed_tls_header.rst +++ b/doc/nrf/libraries/security/nrf_security/doc/mbed_tls_header.rst @@ -16,8 +16,6 @@ Complete the following steps: * `CONFIG_GENERATE_MBEDTLS_CFG_FILE=n`. * `CONFIG_MBEDTLS_CFG_FILE="custom-name-nrf-config.h"`. - * `CONFIG_MBEDTLS_USER_CONFIG_FILE="empty_file.h"`. -#. Create an empty file named :file:`empty_file.h`. #. Edit :file:`custom-name-nrf-config.h` with your custom configuration. #. If the header files are not already in the include path, add them by editing the application build scripts. diff --git a/doc/nrf/libraries/nrf_security/index.rst b/doc/nrf/libraries/security/nrf_security/index.rst similarity index 100% rename from doc/nrf/libraries/nrf_security/index.rst rename to doc/nrf/libraries/security/nrf_security/index.rst diff --git a/doc/nrf/libraries/tfm/index.rst b/doc/nrf/libraries/security/tfm/index.rst similarity index 100% rename from doc/nrf/libraries/tfm/index.rst rename to doc/nrf/libraries/security/tfm/index.rst diff --git a/doc/nrf/libraries/tfm/tfm_ioctl_api.rst b/doc/nrf/libraries/security/tfm/tfm_ioctl_api.rst similarity index 90% rename from doc/nrf/libraries/tfm/tfm_ioctl_api.rst rename to doc/nrf/libraries/security/tfm/tfm_ioctl_api.rst index 9f45289955b..ad5bfc0151f 100644 --- a/doc/nrf/libraries/tfm/tfm_ioctl_api.rst +++ b/doc/nrf/libraries/security/tfm/tfm_ioctl_api.rst @@ -22,7 +22,7 @@ Wrapper functions for these accesses are defined in :file:`tfm_ioctl_ns_api.c` a The supported platform services are defined by :c:struct:`tfm_platform_ioctl_core_reqest_types_t` in :file:`tfm_ioctl_core_api.h`. -.. literalinclude:: ../../../../../modules/tee/tf-m/trusted-firmware-m/platform/ext/target/nordic_nrf/common/core/services/include/tfm_ioctl_core_api.h +.. literalinclude:: ../../../../../../modules/tee/tf-m/trusted-firmware-m/platform/ext/target/nordic_nrf/common/core/services/include/tfm_ioctl_core_api.h :language: c :start-at: /** @brief Supported request types. :end-before: /** @brief Argument list for each platform read service. diff --git a/doc/nrf/libraries/security/trusted_storage.rst b/doc/nrf/libraries/security/trusted_storage.rst new file mode 100644 index 00000000000..47d426d480a --- /dev/null +++ b/doc/nrf/libraries/security/trusted_storage.rst @@ -0,0 +1,169 @@ +.. _trusted_storage_readme: + +Trusted storage +############### + +.. contents:: + :local: + :depth: 2 + +The trusted storage library enables its users to provide integrity, confidentiality and authenticity of stored data using Authenticated Encryption with Associated Data (AEAD) algorithms or cryptographic hash, without the use of TF-M Platform Root of Trust (PRoT). +The library implements the PSA Certified Secure Storage API. + +Overview +******** + +The following subsections give an overview of the library architecture, its interfaces, choices and backends. + +Architecture +============ + +The trusted storage library is designed and implemented in a modular way, which allows and simplifies customization. +This is realized by using backends for the different tasks performed within the trusted storage. + +The library provides users two choices that are interfacing backends: ``TRUSTED_STORAGE_BACKEND`` and ``TRUSTED_STORAGE_STORAGE_BACKEND``. +The backends are also modular, allowing customization of what crypto implementation and the key nonce are provided. + +The following image gives an overview of the default architecture of the trusted storage library. + +.. figure:: images/trusted_storage.svg + :alt: Diagram showing the trusted storage library architecture + + Overview of the trusted storage library architecture + +External storage is not supported by the trusted storage library by default. +To add support for external storage, implement a custom storage backend. + +Interfaces +========== + +The trusted storage library provides two storage interfaces for use with device-protected storage: + +* PSA internal trusted storage, designed to store critical data that must be placed inside internal non-volatile memory. + The size of the storage available by the internal trusted storage API is expected to be limited, and therefore should be used for small, security-critical values. + Examples of assets that require this kind of storage are replay protection values for external storage and keys for use by components of the PSA Root of Trust. +* PSA protected storage, designed to store all other critical data that do not need to be stored inside internal non-volatile memory. + +The two interfaces provide a consistent way for applications to access the storage types, through PSA Internal Trusted Storage API and PSA Protected Storage API. + +Choices and backends +==================== + +The trusted storage library comes with two choices: + +* ``TRUSTED_STORAGE_BACKEND`` that defines a backend for handling of encryption, authentication or other means of validation of the stored data. + It is responsible for what is happening with the data before and after they are read from or written to non-volatile storage. +* ``TRUSTED_STORAGE_STORAGE_BACKEND`` that defines a backend that handles how the data are written to non-volatile storage. + +In other words, ``TRUSTED_STORAGE_BACKEND`` is responsible for modifying the assets before they are forwarded to the ``TRUSTED_STORAGE_STORAGE_BACKEND``, which again handles storing of data in the non-volatile storage. + +The following backends are used in the trusted storage library: + +``TRUSTED_STORAGE_BACKEND_AEAD`` + Uses an AEAD scheme to provide integrity, confidentiality and authenticity. + The trusted storage library provides the ``TRUSTED_STORAGE_BACKEND_AEAD`` backend, but it has support for adding other secure implementation backends to provide various levels of trust, depending on the device security features. + + Uses a separate backend to perform the AEAD operation, set by the Kconfig option :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_CRYPTO`. + The nonce and the key for the AEAD operation are provided by separate backends, allowing a custom implementation. + + For the key, the default choice is to use the :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK` Kconfig option. + With this option, a :ref:`lib_hw_unique_key` and the UID are used to derive an AEAD key. + +``TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS`` + Stores the given assets by using :ref:`Zephyr's settings subsystem `. + The backend requires that Zephyr's settings subsystem is enabled for use (Kconfig option :kconfig:option:`CONFIG_SETTINGS` has to be set). + + The trusted storage library provides the ``TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS`` as a storage backend, but it has support for adding other memory types for storage. + +Requirements +************ + +Before using the trusted storage library with its default settings and options, make sure to meet the following requirements: + +* The hardware unique key (HUK) :ref:`library ` and :ref:`sample ` are enabled and ready for use to derive an AEAD key. +* Zephyr's settings subsystem has to be enabled for use by setting the Kconfig option :kconfig:option:`CONFIG_SETTINGS`. + + * The settings subsystem uses the :ref:`zephyr:nvs_api` file system by default. + This file system has to be mounted to a mount point at application startup. For more information about this, see :ref:`zephyr:file_system_api`. + +.. _trusted_storage_configuration: + +Configuration +************* + +Set the Kconfig option :kconfig:option:`CONFIG_TRUSTED_STORAGE` to enable the trusted storage library. + +Use the Kconfig option :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND` to define the backend that handles encryption and authentication. +If this Kconfig option is set, the configuration defaults to the only currently available option :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD` to use an AEAD scheme for encryption and authentication of stored data. + +Use the Kconfig option :kconfig:option:`CONFIG_TRUSTED_STORAGE_STORAGE_BACKEND` to define the backend that handles how the data are written to and from the non-volatile storage. +If this Kconfig option is set, the configuration defaults to the only currently available option :kconfig:option:`CONFIG_TRUSTED_STORAGE_STORAGE_BACKEND_SETTINGS` to use Zephyr's settings subsystem. + +The following options are used to configure the AEAD backend and its behavior: + +:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_MAX_DATA_SIZE` + Defines the maximum data storage size for the AEAD backend (256 as default value). + +:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_CRYPTO` + Selects what implementation is used to perform the AEAD cryptographic operations. + This option defaults to :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_CRYPTO_PSA_CHACHAPOLY` using the ChaCha20Poly1305 AEAD scheme via PSA APIs. + +:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_NONCE` + Selects what implementation provides AEAD nonce. + You can choose one of the following values when this configuration option is set: + + * :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_NONCE_PSA_SEED_COUNTER` - Selects the PSA Crypto for nonce initial random seed and a counter incrementing nonce for each AEAD encryption. + This is the default option for the AEAD nonce. + * :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_NONCE_CUSTOM` - Selects a custom implementation for AEAD nonce provider. + +:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY` + Selects what implementation provides the AEAD keys. + You can choose one of the following values when this configuration option is set: + + * :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK` - Selects HUK to derive a key based on the UID file. + This is the default selection for the AEAD key provider, and also the only really secure option. + * :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_HASH_UID` - Selects the use of SHA-256 of the UID file as the key. + This option is not as secure as when using HUKs for key derivation as it will only provide integrity of the data. + Use this option only when HUK is not possible to use. + * :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_CUSTOM` - Selects a custom implementation for the AEAD key provider. + +Usage +***** + +The trusted storage library can only be used on a build using a build target with :ref:`CMSE disabled ` (``_cpuapp``). +When you build for ``_cpuapp``, you build the firmware for the application core without CMSE and thus no TF-M. +The library can be used directly on such a build to store important assets. +However, for cryptographic keys we suggest to use the `PSA functions for key management`_. +These APIs will internally use this library to store persistent keys. + +Dependencies +************ + +This library has dependencies to following libraries: + +* :ref:`lib_hw_unique_key` +* :ref:`Zephyr's settings subsystem ` + + +API documentation +***************** + +Protected storage +================= + +| Header file: :file:`include/protected_storage.h` +| Source files: :file:`subsys/secure_storage/src/protected_storage/backend_interface.c` + +.. doxygengroup:: protected_storage + :project: nrf + :members: + +Internal trusted storage +======================== + +| Header file: :file:`include/internal_trusted_storage.h` +| Source files: :file:`subsys/secure_storage/src/internal_trusted_storage/backend_interface.c` + +.. doxygengroup:: internal_trusted_storage + :project: nrf + :members: diff --git a/doc/nrf/libraries/zigbee/index.rst b/doc/nrf/libraries/zigbee/index.rst index dbbd8a0fdb4..b6b20b4458e 100644 --- a/doc/nrf/libraries/zigbee/index.rst +++ b/doc/nrf/libraries/zigbee/index.rst @@ -75,7 +75,7 @@ The following table lists libraries enabled by default for each available Zigbee Read the table symbols in the following manner: * ``✔`` - The library is enabled by default for the given Zigbee sample. -* ``**`` - The library support is available through the :file:`prj_fota.conf` for the given Zigbee sample. +* ``**`` - The library support is available through the :file:`prj_fota.conf` file for the given Zigbee sample. * No symbol - The library is not enabled for the given sample, but you can enable support by following the instructions on the :ref:`ug_zigbee_configuring_libraries`. .. toctree:: diff --git a/doc/nrf/libraries/zigbee/osif.rst b/doc/nrf/libraries/zigbee/osif.rst index 564b3a96935..f232187bddc 100644 --- a/doc/nrf/libraries/zigbee/osif.rst +++ b/doc/nrf/libraries/zigbee/osif.rst @@ -34,6 +34,10 @@ You can also configure the following OSIF-related Kconfig options: Use this option only for testing and debugging your application. * :kconfig:option:`CONFIG_ZIGBEE_HAVE_SERIAL` - Enables the UART serial abstract for the ZBOSS OSIF layer and allows to configure the serial glue layer. For more information, see the :ref:`zigbee_osif_zboss_osif_serial` section. + + .. note:: + Serial abstract must be enabled when using the precompiled ZBOSS libraries since they have dependencies on it. + * :kconfig:option:`CONFIG_ZIGBEE_USE_BUTTONS` - Enables the buttons abstract for the ZBOSS OSIF layer. You can use this option if you want to test ZBOSS examples directly in the |NCS|. * :kconfig:option:`CONFIG_ZIGBEE_USE_DIMMABLE_LED` - Dimmable LED (PWM) abstract for the ZBOSS OSIF layer. @@ -106,8 +110,7 @@ To configure this set of functions, use the following options: * :kconfig:option:`CONFIG_ZIGBEE_UART_RX_BUF_LEN` - This option enables and configures the size of internal RX and TX buffer. * :kconfig:option:`CONFIG_ZBOSS_TRACE_BINARY_NCP_TRANSPORT_LOGGING` - This option enables logging ZBOSS traces in binary format with Zigbee async serial. -The Zigbee ZBOSS OSIF layer serial device needs to be provided in Devicetree -like this: +The Zigbee ZBOSS OSIF layer serial device needs to be provided in devicetree as follows: .. code-block:: devicetree diff --git a/doc/nrf/libraries/zigbee/zigbee_zcl_scenes.rst b/doc/nrf/libraries/zigbee/zigbee_zcl_scenes.rst index 653620ef196..b273d98834d 100644 --- a/doc/nrf/libraries/zigbee/zigbee_zcl_scenes.rst +++ b/doc/nrf/libraries/zigbee/zigbee_zcl_scenes.rst @@ -58,7 +58,7 @@ You must implement these functions in the following manner: Setting the :kconfig:option:`CONFIG_ZIGBEE_SCENES` option allows you to configure the following library-specific Kconfig options: * :kconfig:option:`CONFIG_ZIGBEE_SCENES_ENDPOINT` - This option sets the endpoint number on which the device implements the ZCL scene cluster. -* :kconfig:option:`CONFIG_ZIGBEE_SCENE_TABLE_SIZE` - This options sets the value for the amount of scenes that can be configured. +* :kconfig:option:`CONFIG_ZIGBEE_SCENE_TABLE_SIZE` - This option sets the value for the number of scenes that can be configured. To configure the logging level of the library, use the :kconfig:option:`CONFIG_ZIGBEE_SCENES_LOG_LEVEL` Kconfig option. diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 4fd3efb5d30..1ef1964f2c9 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -19,6 +19,9 @@ .. _`Zephyr Application Configuration`: https://docs.zephyrproject.org/latest/develop/application/index.html#application-configuration .. _`Zephyr Bluetooth LE Security`: https://docs.zephyrproject.org/latest/connectivity/bluetooth/bluetooth-arch.html#security .. _`Pinctrl Migration Utility Script documentation`: https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/utils/pinctrl_nrf_migrate.py +.. _`Zephyr Wi-Fi management API`: https://docs.zephyrproject.org/apidoc/latest/group__wifi__mgmt.html +.. _`Zephyr net capture`: https://docs.zephyrproject.org/latest/samples/net/capture/README.html +.. _`Zephyr net capture Linux setup`: https://docs.zephyrproject.org/latest/connectivity/networking/usbnet_setup.html#usb-device-networking-setup .. ### Source: github.com @@ -26,6 +29,7 @@ .. _`GitHub fork`: https://docs.github.com/en/github/getting-started-with-github/quickstart/fork-a-repo .. _`GitHub duplicate`: https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/duplicating-a-repository +.. _`Amazon Sidewalk Sample IoT App`: https://github.com/aws-samples/aws-iot-core-for-amazon-sidewalk-sample-app .. _`sdk-zephyr`: https://github.com/nrfconnect/sdk-zephyr .. _`official Zephyr repository`: .. _`Zephyr repository`: https://github.com/zephyrproject-rtos/zephyr @@ -36,10 +40,11 @@ .. _`Zephyr issue #27356`: https://github.com/zephyrproject-rtos/zephyr/issues/27356 .. _`Zephyr issue #38516`: https://github.com/zephyrproject-rtos/zephyr/issues/38516 .. _`Zephyr SDK`: https://github.com/zephyrproject-rtos/sdk-ng/releases -.. _`BSEC license`: https://www.bosch-sensortec.com/media/boschsensortec/downloads/software/bme688_development_software/2023_04/license_terms_bme688_bme680_bsec.pdf + .. _`sdk-mcuboot`: https://github.com/nrfconnect/sdk-mcuboot .. _`MCUboot repository`: https://github.com/mcu-tools/mcuboot +.. _`MCUboot Kconfig option`: https://github.com/nrfconnect/sdk-mcuboot/blob/main/boot/zephyr/Kconfig#L370 .. _`sdk-mbedtls`: https://github.com/nrfconnect/sdk-mbedtls .. _`Arm Mbed TLS project`: https://github.com/ARMmbed/mbedtls @@ -60,14 +65,14 @@ .. _`Ethernet over RTT for Linux`: https://github.com/doki-nordic/experimental-eth-rtt-link/ -.. _`Memfault firmware SDK`: https://github.com/memfault/memfault-firmware-sdk + .. _`Memfault entry in the manifest`: https://github.com/nrfconnect/sdk-nrf/blob/20f40501f69bc9bfd2b321704917da1769411936/west.yml#L170-L173 .. _`ANT entry in the manifest`: https://github.com/nrfconnect/sdk-nrf/blob/20f40501f69bc9bfd2b321704917da1769411936/west.yml#L182-L187 -.. _`Golioth Zephyr SDK`: https://github.com/golioth/golioth-zephyr-sdk -.. _`Golioth module.yml`: https://github.com/golioth/golioth-zephyr-sdk/blob/v0.5.0/zephyr/module.yml -.. _`Golioth west-ncs.yml`: https://github.com/golioth/golioth-zephyr-sdk/blob/v0.5.0/west-ncs.yml -.. _`Golioth README nRF Connect SDK`: https://github.com/golioth/golioth-zephyr-sdk/tree/v0.5.0#using-with-nrf-connect-sdk +.. _`Golioth Firmware SDK`: https://github.com/golioth/golioth-firmware-sdk +.. _`Golioth module.yml`: https://github.com/golioth/golioth-firmware-sdk/blob/v0.10.0/zephyr/module.yml +.. _`Golioth west-ncs.yml`: https://github.com/golioth/golioth-firmware-sdk/blob/v0.10.0/west-ncs.yml +.. _`Golioth Firmware SDK NCS doc`: https://github.com/golioth/golioth-firmware-sdk/tree/main/examples/zephyr#using-with-nordics-nrf-connect-sdk .. _`nrfx`: https://github.com/NordicSemiconductor/nrfx/ .. _`Changelog for nrfx 2.2.0`: https://github.com/NordicSemiconductor/nrfx/blob/master/CHANGELOG.md#user-content-220---2020-04-28 @@ -94,6 +99,7 @@ .. _`OpenThread CLI Reference - pollperiod command`: https://github.com/openthread/openthread/blob/main/src/cli/README.md#pollperiod .. _`Commissioner CLI commands`: https://github.com/openthread/openthread/blob/main/src/cli/README_COMMISSIONER.md .. _`Joiner CLI commands`: https://github.com/openthread/openthread/blob/main/src/cli/README_JOINER.md +.. _`BBTC Client`: https://github.com/nrfconnect/sdk-openthread/tree/main/tools/tcat_ble_client .. _`Breathe issue #437`: https://github.com/michaeljones/breathe/issues/437 .. _`Breathe issue #438`: https://github.com/michaeljones/breathe/issues/438 @@ -122,12 +128,13 @@ .. _`ZCL Advanced Platform`: https://github.com/project-chip/zap .. _`ZCL Advanced Platform releases`: https://github.com/project-chip/zap/releases .. _`Matter nRF Connect releases`: https://github.com/nrfconnect/sdk-connectedhomeip/releases -.. _`Matter Certification Policy`: https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/policies/matter_certificate_policy.adoc .. _`Kconfig.mcuboot.defaults`: https://github.com/project-chip/connectedhomeip/blob/master/config/nrfconnect/chip-module/Kconfig.mcuboot.defaults .. _`Matter SDK tagged as v1.0.0`: https://github.com/project-chip/connectedhomeip/releases/tag/v1.0.0 .. _`Testing with Apple Devices`: https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/darwin.md .. _`Matter factory data Kconfig options`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/kconfig/index.html#!CHIP_FACTORY_DATA +.. _`CoreMark GitHub`: https://github.com/eembc/coremark + .. ### Matter links that need updated SHA per release .. _`other controller setups`: https://github.com/nrfconnect/sdk-connectedhomeip/tree/181b0cb/src/controller @@ -136,14 +143,14 @@ .. _`LogModule enumeration`: https://github.com/nrfconnect/sdk-connectedhomeip/blob/181b0cb/src/lib/support/logging/Constants.h .. _`Matter SDK's Logging header`: https://github.com/nrfconnect/sdk-connectedhomeip/blob/181b0cb/src/lib/support/logging/CHIPLogging.h -.. _`bt_nus_service.cpp`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus_service.cpp -.. _`bt_nus_service.h`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus_service.h +.. _`bt_nus_service.cpp`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus/bt_nus_service.cpp +.. _`bt_nus_service.h`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus/bt_nus_service.h .. _`DCL Quick Start Guide`: https://github.com/zigbee-alliance/distributed-compliance-ledger/blob/master/docs/quickStartGuide.adoc .. _`nRF Cloud JSON protocol schemas`: https://github.com/nRFCloud/application-protocols .. _`device_credentials_installer.py`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/device_credentials_installer.py -.. _`nrf_cloud_provision.py`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/README.md#nrf-cloud-device-provisioning +.. _`nrf_cloud_onboard.py`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/README.md#nrf-cloud-device-onboarding .. _`nRF Cloud Utilities Create CA Cert`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/README.md#create-ca-cert .. _`nRF Cloud Utilities Create Device Credentials`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/README.md#create-device-credentials .. _`nRF Cloud Utilities Prerequisites`: https://github.com/nRFCloud/utils/blob/master/python/modem-firmware-1.3%2B/README.md#prerequisites @@ -158,10 +165,6 @@ .. _`fwupd`: https://github.com/fwupd/fwupd -.. _`PR #329 in sdk-homekit repo`: https://github.com/nrfconnect/sdk-homekit/pull/329 - -.. _`PR #332 in sdk-homekit repo`: https://github.com/nrfconnect/sdk-homekit/pull/332 - .. _`docbuild`: https://github.com/nrfconnect/sdk-nrf/blob/main/.github/workflows/docbuild.yml .. _`docpublish`: https://github.com/nrfconnect/sdk-nrf/blob/main/.github/workflows/docpublish.yml @@ -169,14 +172,22 @@ .. _`Azure SDK for Embedded C IoT client libraries`: https://github.com/nrfconnect/azure-sdk-for-c/blob/main/sdk/docs/iot/README.md -.. _`Memfault WebBluetooth Client source code`: https://github.com/memfault/web-ble-example/blob/main/mds.js - .. _`cJSON`: https://github.com/nrfconnect/sdk-cjson .. _`pc-ble-driver-py`: https://github.com/NordicSemiconductor/pc-ble-driver-py .. _`commit #d55314`: https://github.com/nrfconnect/sdk-nrf/commit/d553142f4f37bc324da9869e4837cdd9105e25ab +.. _`zcbor 0.8.0 release notes`: https://github.com/zephyrproject-rtos/zcbor/blob/0.8.0/RELEASE_NOTES.md +.. _`zcbor 0.8.1 release notes`: https://github.com/zephyrproject-rtos/zcbor/blob/0.8.1/RELEASE_NOTES.md + +.. _`nRF Asset Tracker Memfault integration for AWS IoT`: https://github.com/NordicSemiconductor/asset-tracker-cloud-memfault-aws-js +.. _`nRF Asset Tracker Memfault integration for Azure IoT Hub`: https://github.com/NordicSemiconductor/asset-tracker-cloud-memfault-azure-js + +.. _`Memfault firmware SDK`: https://github.com/memfault/memfault-firmware-sdk +.. _`Memfault WebBluetooth Client source code`: https://github.com/memfault/web-ble-example/blob/main/mds.js +.. _`Memfault-SDK`: https://github.com/memfault/memfault-firmware-sdk + .. ### Source: github.io .. _`TinyCBOR`: https://intel.github.io/tinycbor/current/ @@ -184,8 +195,6 @@ .. _`nRF Asset Tracker project`: https://nordicsemiconductor.github.io/asset-tracker-cloud-docs/v2.5.x/docs/project/Index.html .. _`Getting started guide for nRF Asset Tracker for AWS`: https://nordicsemiconductor.github.io/asset-tracker-cloud-docs/v2.5.x/docs/aws/GettingStarted/Index.html .. _`Getting started guide for nRF Asset Tracker for Azure`: https://nordicsemiconductor.github.io/asset-tracker-cloud-docs/v2.5.x/docs/azure/GettingStarted/Index.html -.. _`nRF Asset Tracker Memfault integration for AWS IoT`: https://github.com/NordicSemiconductor/asset-tracker-cloud-memfault-aws-js -.. _`nRF Asset Tracker Memfault integration for Azure IoT Hub`: https://github.com/NordicSemiconductor/asset-tracker-cloud-memfault-azure-js .. _`nRF Asset Tracker Memfault integration`: https://nordicsemiconductor.github.io/asset-tracker-cloud-docs/v2.5.x/docs/memfault/Index.html .. _`latest release notes for nRF Connect for Visual Studio Code`: https://nrfconnect.github.io/vscode-nrf-connect/release_notes/connect/2022.11.140.html @@ -195,23 +204,30 @@ .. _`How to work with Devicetree Visual Editor`: https://nrfconnect.github.io/vscode-nrf-connect/guides/work_with_devicetree_editor.html .. _`Devicetree support overview`: https://nrfconnect.github.io/vscode-nrf-connect/guides/ncs_configure_app.html#devicetree-overview .. _`Devicetree language support`: https://nrfconnect.github.io/vscode-nrf-connect/guides/ncs_configure_app.html#devicetree-language-support +.. _`How to work with boards and devices`: https://nrfconnect.github.io/vscode-nrf-connect/guides/bd_work_with_boards.html .. _`How to install the extension`: .. _`Installing on Linux`: https://nrfconnect.github.io/vscode-nrf-connect/get_started/install.html .. _`How to build an application`: https://nrfconnect.github.io/vscode-nrf-connect/get_started/build_app_ncs.html .. _`Migrating IDE`: https://nrfconnect.github.io/vscode-nrf-connect/reference/ui_sidebar_welcome.html#open-an-existing-application .. _`How to change SDK and toolchain versions`: https://nrfconnect.github.io/vscode-nrf-connect/guides/extension_migrate_sdk.html +.. _`How to flash an application`: .. _`How to debug an application`: .. _`How to connect to the terminal`: https://nrfconnect.github.io/vscode-nrf-connect/get_started/quick_debug.html .. _`Debugging overview`: https://nrfconnect.github.io/vscode-nrf-connect/guides/debug_concepts.html .. _`How to debug`: https://nrfconnect.github.io/vscode-nrf-connect/guides/debug_use.html .. _`How to debug applications for a multi-core System on Chip`: https://nrfconnect.github.io/vscode-nrf-connect/guides/debug_use.html#how-to-debug-applications-for-a-multi-core-system-on-chip +.. _`source control with west`: https://nrfconnect.github.io/vscode-nrf-connect/guides/west_about.html .. _`west module management`: https://nrfconnect.github.io/vscode-nrf-connect/guides/west_module_management.html .. _`Custom launch and debug configurations`: https://nrfconnect.github.io/vscode-nrf-connect/guides/debug_advanced.html#custom-launch-and-debug-configurations +.. _`Binding custom tasks to actions`: https://nrfconnect.github.io/vscode-nrf-connect/guides/build_bind_tasks.html .. _`Application-specific flash options`: https://nrfconnect.github.io/vscode-nrf-connect/guides/bd_work_with_boards.html#how-to-flash-boards +.. _`CMake build system`: https://nrfconnect.github.io/vscode-nrf-connect/guides/build_overview.html#cmake-build-system .. _`How to work with build configurations`: https://nrfconnect.github.io/vscode-nrf-connect/guides/build_config.html +.. _`Details View`: https://nrfconnect.github.io/vscode-nrf-connect/reference/ui_sidebar_details.html .. _`Memory report`: https://nrfconnect.github.io/vscode-nrf-connect/guides/memory_overview.html .. _`Kconfig action in the Actions View`: https://nrfconnect.github.io/vscode-nrf-connect/reference/ui_sidebar_actions.html .. _`Create a new application`: https://nrfconnect.github.io/vscode-nrf-connect/reference/ui_sidebar_welcome.html#create-a-new-application +.. _`Browse samples`: https://nrfconnect.github.io/vscode-nrf-connect/reference/ui_sidebar_welcome.html#browse-samples .. _`SPAKE2+ Python Tool page`: https://project-chip.github.io/connectedhomeip-doc/scripts/tools/spake2p/README.html @@ -220,6 +236,17 @@ .. _`Memfault WebBluetooth Client`: https://memfault.github.io/web-ble-example/ .. _`PSA Cryptography API 1.0.1`: https://armmbed.github.io/mbed-crypto/1.0.1/html/index.html +.. _`PSA functions for key management`: https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html + +.. _`Sidewalk documentation`: https://nrfconnect.github.io/sdk-sidewalk/ +.. _`Setting up the SDK for Amazon Sidewalk`: https://nrfconnect.github.io/sdk-sidewalk/setting_up_sidewalk_environment/setting_up_sdk.html + +.. _`Memfault WebBluetooth Client`: https://memfault.github.io/web-ble-example/ + +.. ### Source: githubusercontent.com + +.. _`raw XML`: https://raw.githubusercontent.com/OpenMobileAlliance/lwm2m-registry/prod/version_history/3300-1_0.xml +.. _`Amazon license`: https://raw.githubusercontent.com/nrfconnect/sdk-sidewalk/main/LICENSE.txt .. ### Source: developer.nordicsemi.com @@ -234,8 +261,11 @@ .. _`nRF Connect SDK latest documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/index.html .. _`known issues page on the main branch`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html +.. _`known issues for nRF Connect SDK v2.6.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-6-0 +.. _`known issues for nRF Connect SDK v2.5.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-5-2 .. _`known issues for nRF Connect SDK v2.5.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-5-1 .. _`known issues for nRF Connect SDK v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-5-0 +.. _`known issues for nRF Connect SDK v2.4.3`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-4-3 .. _`known issues for nRF Connect SDK v2.4.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-4-2 .. _`known issues for nRF Connect SDK v2.4.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-4-1 .. _`known issues for nRF Connect SDK v2.4.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/known_issues.html?v=v2-4-0 @@ -267,57 +297,60 @@ .. _`connecting to nRF Cloud`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/networking/nrf_cloud.html#connecting .. _`API documentation`: -.. _`external ZBOSS development guide and API documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/zigbee_devguide.html -.. _`Stack commissioning start sequence`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#stack_start_initiation -.. _`ZBOSS NCP Host`: https://developer.nordicsemi.com/Zigbee/ncp_sdk_for_host/ncp_host_v2.2.1.zip -.. _`NCP Host documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/zboss_ncp_host_intro.html -.. _`Rebuilding the ZBOSS libraries for host`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/zboss_ncp_host.html#rebuilding_libs -.. _`process the frame`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#process_zcl_cmd -.. _`declaring custom cluster`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#cluster_declaration_custom -.. _`Configuring sleepy behavior for end devices`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/zigbee_prog_principles.html#zigbee_power_optimization_sleepy -.. _`zboss_signal_handler()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#gae05c0ff285cfd03e0997fe438e8047fc -.. _`Common ZCL terms and definitions`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#ZCL_definitions -.. _`Declaring attributes`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#att_declaration -.. _`Declaring endpoint`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#endpoint_dec -.. _`Declaring simple descriptors`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#simple_desc_declaration -.. _`Declaring Zigbee device context`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#zigbee_device_context_dec -.. _`Declaring Zigbee device context with multiple endpoints`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#zigbee_device_context_mult_ep_dec -.. _`Resetting to factory defaults`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#reset_factory_defaults -.. _`Registering device context`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#register_zigbee_device -.. _`Support for Zigbee commissioning`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/using_zigbee__z_c_l.html#zcl_zigbee_commissioning -.. _`BDB Commissioning API`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__api.html - -.. _`ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga18f5e7ddfefb7d01ef98f696a9694d79 -.. _`ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga3eb4631c12c345991be2461566c150e9 -.. _`ZB_ZDO_SIGNAL_SKIP_STARTUP`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#gab2b9e7a13fd471d7bb642655d825a04e -.. _`ZB_BDB_SIGNAL_DEVICE_FIRST_START`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#gab55565980ef0580712f8dc160b01ea06 -.. _`ZB_BDB_SIGNAL_DEVICE_REBOOT`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga3e9d86f42d2c6c27240f423a40fb152b -.. _`ZB_BDB_SIGNAL_FORMATION`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga342d4176c8932ff8ab0d8d6f997fa603 -.. _`ZB_BDB_SIGNAL_STEERING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga25a801841c95d6daddb9c60b39542b13 -.. _`ZB_ZDO_SIGNAL_LEAVE`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zb__comm__signals.html#ga7942f336484c4fbb85626951480b2bba -.. _`ZB_HA_DECLARE_ON_OFF_SWITCH_CLUSTER_LIST`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__ha__on__off__switch.html#ga566dbde2d408c46c488460219edf6002 -.. _`ZB_AF_REGISTER_DEVICE_CTX`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__af__management__service.html#ga2ba409e0ae3e25032b673a5f85859a45 -.. _`ZB_HA_DECLARE_TEMPERATURE_SENSOR_CLUSTER_LIST`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__ha__temperature__sensor.html#ga1baeb195bbce720ee97cf9c879726cbb -.. _`zb_zcl_device_callback_param_t`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#ga0dfcc989252b93252f8bb1d27d2639fa -.. _`zb_zcl_device_callback_id_t`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#gad27454b213ce8a00540ebc75288966ad -.. _`ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#gga35caa2e3a9ef37535b1f75e0fe919266a8a87688c465e80b46ad821741a60fe84 -.. _`zb_bdb_set_legacy_device_support`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__params.html#ga8bf3b3beef192c00bcdca17ad1240921 -.. _`zboss_start()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.1.177/group__zb__general__start.html#ga31b4d46033aaf6a400409d03bd40d392 -.. _`bdb_start_top_level_commissioning()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__start.html#ga0b54e93a19cadc5fc02df8eab18ecd45 -.. _`zb_bdb_commissioning_mode_mask_e`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__start.html#ga9c44bbce9f6f6b19b623837914959c02 -.. _`ZB_BDB_NETWORK_STEERING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ae31d4a2067eb711a43f7049b08710299 -.. _`ZB_BDB_NETWORK_FORMATION`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ac723cfd38f78c08a673ec3664539027c -.. _`ZB_BDB_FINDING_N_BINDING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ad9bcb56a6668b6ba6f37edc73a796b58 -.. _`zb_bdb_finding_binding_initiator()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.2.1/group__zboss__bdb__comm__fb.html#gae6fd60a050559ef0aa3c3e5ec32bc515 +.. _`external ZBOSS development guide and API documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/zigbee_devguide.html +.. _`Stack commissioning start sequence`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#stack_start_initiation +.. _`ZBOSS NCP Host`: https://developer.nordicsemi.com/Zigbee/ncp_sdk_for_host/ncp_host_v2.2.2.zip +.. _`NCP Host documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/zboss_ncp_host_intro.html +.. _`Rebuilding the ZBOSS libraries for host`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/zboss_ncp_host.html#rebuilding_libs +.. _`process the frame`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#process_zcl_cmd +.. _`declaring custom cluster`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#cluster_declaration_custom +.. _`Configuring sleepy behavior for end devices`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/zigbee_prog_principles.html#zigbee_power_optimization_sleepy +.. _`zboss_signal_handler()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#gae05c0ff285cfd03e0997fe438e8047fc +.. _`Common ZCL terms and definitions`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#ZCL_definitions +.. _`Declaring attributes`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#att_declaration +.. _`Declaring endpoint`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#endpoint_dec +.. _`Declaring simple descriptors`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#simple_desc_declaration +.. _`Declaring Zigbee device context`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#zigbee_device_context_dec +.. _`Declaring Zigbee device context with multiple endpoints`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#zigbee_device_context_mult_ep_dec +.. _`Resetting to factory defaults`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#reset_factory_defaults +.. _`Registering device context`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#register_zigbee_device +.. _`Support for Zigbee commissioning`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/using_zigbee__z_c_l.html#zcl_zigbee_commissioning +.. _`BDB Commissioning API`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__api.html + +.. _`ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga18f5e7ddfefb7d01ef98f696a9694d79 +.. _`ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga3eb4631c12c345991be2461566c150e9 +.. _`ZB_ZDO_SIGNAL_SKIP_STARTUP`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#gab2b9e7a13fd471d7bb642655d825a04e +.. _`ZB_BDB_SIGNAL_DEVICE_FIRST_START`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#gab55565980ef0580712f8dc160b01ea06 +.. _`ZB_BDB_SIGNAL_DEVICE_REBOOT`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga3e9d86f42d2c6c27240f423a40fb152b +.. _`ZB_BDB_SIGNAL_FORMATION`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga342d4176c8932ff8ab0d8d6f997fa603 +.. _`ZB_BDB_SIGNAL_STEERING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga25a801841c95d6daddb9c60b39542b13 +.. _`ZB_ZDO_SIGNAL_LEAVE`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__comm__signals.html#ga7942f336484c4fbb85626951480b2bba +.. _`ZB_HA_DECLARE_ON_OFF_SWITCH_CLUSTER_LIST`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__ha__on__off__switch.html#ga566dbde2d408c46c488460219edf6002 +.. _`ZB_AF_REGISTER_DEVICE_CTX`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__af__management__service.html#ga2ba409e0ae3e25032b673a5f85859a45 +.. _`ZB_HA_DECLARE_TEMPERATURE_SENSOR_CLUSTER_LIST`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__ha__temperature__sensor.html#ga1baeb195bbce720ee97cf9c879726cbb +.. _`zb_zcl_device_callback_param_t`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#ga0dfcc989252b93252f8bb1d27d2639fa +.. _`zb_zcl_device_callback_id_t`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#gad27454b213ce8a00540ebc75288966ad +.. _`ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group___z_b___z_c_l___i_n_i_t_i_a_l_i_z_a_t_i_o_n.html#gga35caa2e3a9ef37535b1f75e0fe919266a8a87688c465e80b46ad821741a60fe84 +.. _`zb_bdb_set_legacy_device_support`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__params.html#ga8bf3b3beef192c00bcdca17ad1240921 +.. _`zboss_start()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zb__general__start.html#ga31b4d46033aaf6a400409d03bd40d392 +.. _`bdb_start_top_level_commissioning()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__start.html#ga0b54e93a19cadc5fc02df8eab18ecd45 +.. _`zb_bdb_commissioning_mode_mask_e`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__start.html#ga9c44bbce9f6f6b19b623837914959c02 +.. _`ZB_BDB_NETWORK_STEERING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ae31d4a2067eb711a43f7049b08710299 +.. _`ZB_BDB_NETWORK_FORMATION`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ac723cfd38f78c08a673ec3664539027c +.. _`ZB_BDB_FINDING_N_BINDING`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__start.html#gga9c44bbce9f6f6b19b623837914959c02ad9bcb56a6668b6ba6f37edc73a796b58 +.. _`zb_bdb_finding_binding_initiator()`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/zboss/3.11.3.0/group__zboss__bdb__comm__fb.html#gae6fd60a050559ef0aa3c3e5ec32bc515 .. _`TF-M documentation`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/tfm/index.html .. _`TF-M secure partition integration guide`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/tfm/integration_guide/services/tfm_secure_partition_addition.html -.. _`TF-M ITS`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/tfm/technical_references/design_docs/tfm_its_service.html +.. _`TF-M ITS`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/tfm/integration_guide/services/tfm_its_integration_guide.html .. _`nRF socket options`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrfxlib/nrf_modem/doc/sockets.html#socket-options +.. _`Repositories and revisions for v2.6.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.6.0/nrf/releases_and_maturity/repository_revisions.html +.. _`Repositories and revisions for v2.5.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.2/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.5.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.1/nrf/releases_and_maturity/repository_revisions.html -.. _`Repositories and revisions for v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.0/nrf/introduction.html#ncs-repository-revisions +.. _`Repositories and revisions for v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.0/nrf/releases_and_maturity/repository_revisions.html +.. _`Repositories and revisions for v2.4.3`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.3/nrf/introduction.html#ncs-repository-revisions .. _`Repositories and revisions for v2.4.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.2/nrf/introduction.html#ncs-repository-revisions .. _`Repositories and revisions for v2.4.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrf/introduction.html#ncs-repository-revisions .. _`Repositories and revisions for v2.4.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.0/nrf/introduction.html#ncs-repository-revisions @@ -335,8 +368,11 @@ .. _`Repositories and revisions for v1.9.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrf/introduction.html#repositories-and-revisions .. _`Repositories and revisions`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.0/nrf/introduction.html#repositories-and-revisions +.. _`Modem library changelog for v2.6.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.6.0/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog +.. _`Modem library changelog for v2.5.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.2/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v2.5.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.1/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.0/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog +.. _`Modem library changelog for v2.4.3`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.3/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v2.4.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.2/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v2.4.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v2.4.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.0/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog @@ -354,8 +390,11 @@ .. _`Modem library changelog for v1.9.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog .. _`Modem library changelog for v1.9.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.0/nrfxlib/nrf_modem/doc/CHANGELOG.html#nrf-modem-changelog +.. _`LwM2M carrier library changelog for v2.6.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.6.0/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog +.. _`LwM2M carrier library changelog for v2.5.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.2/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v2.5.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.1/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.5.0/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog +.. _`LwM2M carrier library changelog for v2.4.3`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.3/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v2.4.2`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.2/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v2.4.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v2.4.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.0/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog @@ -373,6 +412,10 @@ .. _`LwM2M carrier library changelog for v1.9.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog .. _`LwM2M carrier library changelog for v1.9.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.0/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.html#liblwm2m-carrier-changelog +.. _`Migration guide for nRF Connect SDK v2.6.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/migration/migration_guide_2.6.html +.. _`Migration guide for nRF Connect SDK v2.5.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/migration/migration_guide_2.5.html +.. _`Migration guide for nRF Connect SDK v2.0.0`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/releases_and_maturity/migration/migration_guide_1.x_to_2.x.html + .. _`Matter weather station application from the v2.1.1`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.1/nrf/applications/matter_weather_station/README.html .. _`CONFIG_BT_CTLR_TX_PWR_MINUS`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/kconfig/index.html#!CONFIG_BT_CTLR_TX_PWR_MINUS @@ -388,6 +431,8 @@ .. _`Capabilities for the LE Audio Controller Subsystem for nRF5340`: https://developer.nordicsemi.com/nRF_Connect_SDK/nrf5340_audio/bt_ll_acs_nrf53/bt_ll_acs_nrf53_capabilities.pdf +.. _`nRF9160: GPS with SUPL client library`: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.2.0/nrf/samples/nrf9160/gps/README.html + .. ### Source: www.nordicsemi.com .. _`Nordic Semiconductor website`: https://www.nordicsemi.com/ @@ -409,9 +454,10 @@ .. _`nRF9160 Certifications`: https://www.nordicsemi.com/Products/Low-power-Cellular-IoT/nRF9160-Certifications .. _`nRF9161 Certifications`: https://www.nordicsemi.com/Products/Wireless/Low-power-cellular-IoT/nRF91-Series-certifications/nRF9161-Global-and-regulatory?lang=en#infotabs +.. _`nRF91 Series certifications`: https://www.nordicsemi.com/Products/Wireless/Low-power-cellular-IoT/nRF91-Series-certifications?lang=en#infotabs .. _`Energy efficiency`: https://www.nordicsemi.com/Products/Low-power-cellular-IoT/What-is-cellular-IoT#energy_efficiency - -.. _`nRF9161 Objective Product Specification`: https://www.nordicsemi.com/-/media/Software-and-other-downloads/SiP/nRF91x1-SiP/nRF9161_OPS_v0.7.pdf +.. _`Cellular IoT unique features`: https://www.nordicsemi.com/Products/Low-power-cellular-IoT/Unique-Features?lang=en#infotabs +.. _`Cellular IoT SiPs`: https://www.nordicsemi.com/Products/Low-power-cellular-IoT/Products?lang=en#infotabs .. _`nRF52840 DK Downloads`: https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK/Download#infotabs .. _`nRF52840 DK product page`: https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK/ @@ -423,6 +469,8 @@ .. _`nRF5340 DK Downloads`: https://www.nordicsemi.com/Products/Development-hardware/nRF5340-DK/Download?lang=en#infotabs .. _`nRF5340 DK product page`: https://www.nordicsemi.com/Products/Development-hardware/nRF5340-DK/ +.. _`nRF7002 DK Downloads`: https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK/Download?lang=en#infotabs + .. _`Nordic Thingy:53`: .. _`Thingy:53 product page`: https://www.nordicsemi.com/thingy53 .. _`Nordic Thingy:53 Downloads`: https://www.nordicsemi.com/Products/Development-hardware/Nordic-Thingy-53/Downloads#infotabs @@ -444,10 +492,6 @@ .. _`iBasis network coverage spreadsheet`: https://www.nordicsemi.com/-/media/Software-and-other-downloads/3rd-party/iBasis-simplified-coverage-map-for-web.pdf?la=en&hash=CA7DBF400243D8A7A7BDA94873B50E73C26B4FAC -.. _`Onomondo LTE-M coverage`: https://onomondo.com/product/coverage/lte-m-networks/ - -.. _`Onomondo NB-IoT coverage`: https://onomondo.com/product/coverage/nb-iot-networks/ - .. _`Contact Us`: https://www.nordicsemi.com/About-us/Contact-Us .. _`Nordic Semiconductor Wi-Fi products`: https://www.nordicsemi.com/Products/WiFi @@ -456,7 +500,7 @@ .. #### Source: www.nordicsemi.com/Events/ - +.. _`nRF Connect SDK v2.6.0 webinar`: https://www.nordicsemi.com/Events/2024/Webinar-Exciting-new-features-in-nRF-Connect-SDK-v260 .. _`nRF Connect SDK v2.5.0 webinar`: https://www.nordicsemi.com/Events/2023/Webinar-Exciting-new-features-in-nRF-Connect-SDK-v250 .. _`nRF Connect SDK v2.4.0 webinar`: https://www.nordicsemi.com/Events/2023/Webinar-Exciting-new-features-in-nRF-Connect-SDK-v240 .. _`nRF Connect SDK v2.3.0 webinar`: https://www.nordicsemi.com/Events/2023/Webinar-Exciting-new-features-in-nRF-Connect-SDK-v23?utm_campaign=2023%20Webinars&utm_source=developer.nordicsemi.com&utm_medium=Release%20notes%20%7C%20Webinar-link%20%7C%20Exciting%20new%20features%20in%20nRF%20Connect%20SDK%20v2.3&utm_content=Release%20notes%20%7C%20Webinar-link%20%7C%20Exciting%20new%20features%20in%20nRF%20Connect%20SDK%20v2.3 @@ -493,56 +537,103 @@ .. _`nRF Edge Impulse mobile app`: https://cm.nordicsemi.com/Products/Development-tools/nrf-edge-impulse -.. ### Source: infocenter.nordicsemi.com +.. ### Source: docs.nordicsemi.com -.. _`Nordic Semiconductor Infocenter`: https://infocenter.nordicsemi.com/index.jsp +.. _`Nordic Semiconductor TechDocs`: https://docs.nordicsemi.com + +.. _`nRF Connect Board Configurator`: https://docs.nordicsemi.com/bundle/nrf-connect-board-configurator/page/index.html + +.. _`nRF Connect Serial Terminal`: https://docs.nordicsemi.com/bundle/nrf-connect-serial-terminal/page/index.html +.. _`Connecting using Serial Terminal`: https://docs.nordicsemi.com/bundle/nrf-connect-serial-terminal/page/connecting.html +.. _`Serial Terminal configuration`: https://docs.nordicsemi.com/bundle/nrf-connect-serial-terminal/page/configuration.html + +.. _`nRF Connect Bluetooth Low Energy`: https://docs.nordicsemi.com/bundle/nrf-connect-ble/page/index.html + +.. _`Cellular Monitor`: https://docs.nordicsemi.com/bundle/nrf-connect-cellularmonitor/page/index.html +.. _`Managing credentials`: https://docs.nordicsemi.com/bundle/nrf-connect-cellularmonitor/page/managing_credentials.html + +.. _`nRF Connect Direct Test Mode`: https://docs.nordicsemi.com/bundle/nrf-connect-direct-test-mode/page/index.html + +.. _`nRF Connect Programmer`: https://docs.nordicsemi.com/bundle/nrf-connect-programmer/page/index.html +.. _`Programming the nRF52840 Dongle`: +.. _`Programming a Development Kit`: https://docs.nordicsemi.com/bundle/nrf-connect-programmer/page/programming_dk.html + +.. _`nRF Sniffer for Bluetooth LE`: https://docs.nordicsemi.com/bundle/nrfutil/page/nrfutil-ble-sniffer/guides/overview.html + +.. _`nRF Thread Topology Monitor`: https://docs.nordicsemi.com/bundle/ug_nrf_ttm/page/UG/nrf_ttm/ttm_introduction.html +.. _`nRF Sniffer for 802.15.4`: https://docs.nordicsemi.com/bundle/ug_sniffer_802154/page/UG/sniffer_802154/intro_802154.html +.. _`Configuring Wireshark for Zigbee`: https://docs.nordicsemi.com/bundle/ug_sniffer_802154/page/UG/sniffer_802154/configuring_sniffer_802154_zigbee.html + +.. _`Power Profiler Kit II (PPK2)`: https://docs.nordicsemi.com/bundle/ug_ppk2/page/UG/ppk/PPK_user_guide_Intro.html +.. _`Install the Power Profiler app`: https://docs.nordicsemi.com/bundle/ug_ppk2/page/UG/common/nrf_connect_app_installing.html +.. _`Using the Power Profiler app`: https://docs.nordicsemi.com/bundle/ug_ppk2/page/UG/ppk/PPK_user_guide_Running_the_software.html +.. _`nRF Connect Power Profiler`: https://docs.nordicsemi.com/bundle/nrf-connect-ppk/page/index.html + +.. _`sysbuild support`: https://docs.nordicsemi.com/bundle/nrf-connect-vscode/page/guides/build_overview.html#system-build-sysbuild -.. _`nRF Connect Serial Terminal`: https://infocenter.nordicsemi.com/topic/ug_serial_terminal/UG/serial_terminal/intro.html -.. _`Cellular Monitor`: https://infocenter.nordicsemi.com/topic/ug_cellular_monitor/UG/cellular_monitor/intro.html -.. _`Managing credentials`: https://infocenter.nordicsemi.com/topic/ug_cellular_monitor/UG/cellular_monitor/cellular_mon_cert_manager.html +.. _`Electrical specification for nRF7002`: https://docs.nordicsemi.com/bundle/ps_nrf7002/page/chapters/elspec/doc/electrical_specification.html -.. _`nRF Connect Programmer`: https://infocenter.nordicsemi.com/topic/ug_nc_programmer/UG/nrf_connect_programmer/ncp_introduction.html -.. _`Programming the nRF52840 Dongle`: https://infocenter.nordicsemi.com/topic/ug_nc_programmer/UG/nrf_connect_programmer/ncp_programming_dongle.html -.. _`Programming a Development Kit`: https://infocenter.nordicsemi.com/topic/ug_nc_programmer/UG/common/ncp_programming_dk.html +.. ### Source: infocenter.nordicsemi.com + +.. _`Nordic Semiconductor Infocenter`: https://infocenter.nordicsemi.com/index.jsp .. _`nRF pynrfjprog`: https://infocenter.nordicsemi.com/topic/ug_pynrfjprog/UG/pynrfjprog/pynrfjprog_lpage.html .. _`nRF9160 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf9160/nRF9160_html5_keyfeatures.html -.. _`nRF9160 GPS receiver specification`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf9160%2Fgps.html&cp=2_0_0_7 +.. _`nRF9160 GPS receiver specification`: https://infocenter.nordicsemi.com/topic/ps_nrf9160/gps.html .. _`nRF9160 SiP pin configuration`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/sip_pin_configuration/sip_pin_configuration.html +.. _`Measuring current on nRF9160 DK`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/hw_measure_current.html .. _`nRF9160 DK GPS`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/gps.html +.. _`nWP044 - Best practices for cellular IoT development`: https://infocenter.nordicsemi.com/topic/nwp_044/WP/nwp_044/lte_technology.html +.. _`Security protocol for cellular IoT`: https://infocenter.nordicsemi.com/topic/nwp_044/WP/nwp_044/security_protocols.html + .. _`nRF9160 DK Hardware`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/intro.html .. _`nRF9160 DK board control section in the nRF9160 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/board_controller.html .. _`External memory section in the nRF9160 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/external_memory.html .. _`Device programming section in the nRF9160 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/mcu_device_programming.html .. _`VDD supply rail section in the nRF9160 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/power_sources_vdd.html -.. _`nRF9161 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf9160/nRF9160_html5_keyfeatures.html +.. _`nRF9161 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf9161/nRF9161_html5_keyfeatures.html +.. _`nRF9161 GPS receiver specification`: https://infocenter.nordicsemi.com/topic/ps_nrf9161/gps.html -.. _`nRF9161 DK Hardware`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/intro.html +.. _`nRF9161 DK Hardware`: https://infocenter.nordicsemi.com/topic/ug_nrf9161_dk/UG/nrf91_DK/intro.html +.. _`Measuring current on nRF9161 DK`: https://infocenter.nordicsemi.com/topic/ug_nrf9161_dk/UG/nrf91_DK/measuring_current/hw_measure_current.html .. _`AT Commands Reference Guide`: .. _`nRF9160 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/intro_nrf9160.html -.. _`band lock section in the AT Commands reference document`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xbandlock.html -.. _`system mode section in the AT Commands reference document`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xsystemmode.html +.. _`band lock section in the AT Commands reference document`: +.. _`band lock section in the nRF9160 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xbandlock.html +.. _`system mode section in the AT Commands reference document`: +.. _`system mode section in the nRF9160 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xsystemmode.html .. _`Credential storage management %CMNG`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/security/cmng.html -.. _`Packet Domain AT commands`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/packet_domain/packet_domain.html?cp=2_1_6 -.. _`3GPP Release 14 features AT command`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fref_at_commands%2FREF%2Fat_commands%2Fnw_service%2Frel14feat_read.html&cp=2_1_7_16_1 +.. _`Packet Domain AT commands`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/packet_domain/packet_domain.html +.. _`3GPP Release 14 features AT command`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/nw_service/rel14feat_read.html .. _`AT+CNEC set command`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mobile_termination_errors/cnec_set.html .. _`AT+CGEREP set command`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/packet_domain/cgerep_set.html .. _`AT%CONEVAL`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/coneval.html -.. _`Modem trace AT command documentation`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xmodemtrace.html +.. _`Modem trace AT command documentation`: +.. _`modem trace activation %XMODEMTRACE`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xmodemtrace.html .. _`Battery voltage low level %XVBATLOWLVL`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/mob_termination_ctrl_status/xvbatlowlvl.html -.. _`Debugging nRF5340 with SES`: https://infocenter.nordicsemi.com/topic/ug_gsg_ncs/UG/gsg/debug.html?cp=1_1_0_7 +.. _`Power saving mode setting`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/nw_service/cpsms.html +.. _`Release Assistance Indication (RAI)`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/nw_service/xrai.html .. _`nRF91x1 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/intro_nrf91x1.html +.. _`band lock section in the nRF91x1 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/mob_termination_ctrl_status/xbandlock.html +.. _`system mode section in the nRF91x1 AT Commands Reference Guide`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/mob_termination_ctrl_status/xsystemmode.html +.. _`nRF91x1 battery voltage low level %XVBATLOWLVL`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/mob_termination_ctrl_status/xvbatlowlvl.html +.. _`nRF91x1 credential storage management %CMNG`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/security/cmng.html +.. _`nRF91x1 AT+CGEREP set command`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/packet_domain/cgerep_set.html +.. _`nRF91x1 packet Domain AT commands`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/packet_domain/packet_domain.html +.. _`nRF91x1 AT+CNEC set command`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/mobile_termination_errors/cnec_set.html +.. _`nRF91x1 Power saving mode setting`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/nw_service/cpsms.html +.. _`nRF91x1 modem trace activation %XMODEMTRACE`: https://infocenter.nordicsemi.com/topic/ref_at_commands_nrf91x1/REF/at_commands/mob_termination_ctrl_status/xmodemtrace.html .. _`nRF5340 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf5340/keyfeatures_html5.html .. _`nRF5340 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf5340_dk/UG/dk/intro.html .. _`Execute in place page in the nRF5340 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf5340/qspi.html#execute_in_place -.. _`nRF5340 DK Compatibility Matrix`: https://infocenter.nordicsemi.com/topic/comp_matrix_nrf5340/COMP/nrf5340/nrf5340_comp_matrix.html +.. _`nRF5340 DK Compatibility Matrix`: https://docs.nordicsemi.com/bundle/comp_matrix_nrf5340/page/COMP/nrf5340/nrf5340_comp_matrix.html .. _`nRF5340 Audio DK Hardware`: https://infocenter.nordicsemi.com/topic/ug_nrf5340_audio/UG/nrf5340_audio/intro.html .. _`Requirements for external flash memory DFU`: https://infocenter.nordicsemi.com/topic/ug_nrf5340_audio/UG/nrf5340_audio/hw_external_memory.html @@ -553,7 +644,7 @@ .. _`System OFF mode`: https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html?cp=5_0_0_4_2_2#unique_220399309 .. _`nRF52840 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf52840_dk/UG/dk/intro.html .. _`nRF52840 Dongle User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf52840_dongle/UG/nrf52840_Dongle/intro.html -.. _`nRF52840 DK Compatibility Matrix`: https://infocenter.nordicsemi.com/topic/comp_matrix_nrf52840/COMP/nrf52840/nrf52840_comp_matrix.html +.. _`nRF52840 DK Compatibility Matrix`: https://docs.nordicsemi.com/bundle/comp_matrix_nrf52840/page/COMP/nrf52840/nrf52840_comp_matrix.html .. _`nRF52833 Product Specification`: https://infocenter.nordicsemi.com/topic/ps_nrf52833/keyfeatures_html5.html .. _`nRF52833 DK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf52833_dk/UG/dk/intro.html @@ -588,6 +679,9 @@ .. _`nRF70 Series power states`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf7002%2Fchapters%2Ffunctional%2Fdoc%2Fpower_states.html&cp=3_0_0_4_0 +.. _`nRF7002 EK User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf7002_ek/UG/nrf7002_EK/intro.html +.. _`nRF7002 EB User Guide`: https://infocenter.nordicsemi.com/topic/ug_nrf7002_eb/UG/nrf7002_EB/intro.html + .. _`Programming SoCs with nrfjprog`: https://infocenter.nordicsemi.com/topic/ug_nrf_cltools/UG/cltools/nrf_nrfjprogexe.html .. _`Nordic Thingy:53 Hardware`: https://infocenter.nordicsemi.com/topic/ug_thingy53/UG/thingy53/intro/frontpage.html @@ -602,6 +696,7 @@ .. _`nPM1300`: https://infocenter.nordicsemi.com/topic/struct_pmic/struct/npm1300.html .. _`nPM1300 EK User Guide`: https://infocenter.nordicsemi.com/topic/ug_npm1300_ek/UG/nPM1300_EK/intro.html +.. _`AP-Protect for nRF9161`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf9161%2Fdif.html&anchor=ariaid-title3 .. _`Debugger access protection for nRF9160`: https://infocenter.nordicsemi.com/topic/ps_nrf9160/dif.html#debugger_access .. _`AP-Protect for nRF5340`: https://infocenter.nordicsemi.com/topic/ps_nrf5340/debugandtrace.html#access_port_protection .. _`AP-Protect for nRF52840`: https://infocenter.nordicsemi.com/topic/ps_nrf52840/dif.html#concept_udr_mns_1s @@ -615,10 +710,6 @@ .. _`Mobile network operator certifications`: https://infocenter.nordicsemi.com/topic/comp_matrix_nrf9160/COMP/nrf9160/nrf9160_operator_certifications.html .. _`Modem firmware compatibility matrix`: https://infocenter.nordicsemi.com/topic/comp_matrix_nrf9160/COMP/nrf9160/nrf9160_modem_fw.html -.. _`Power saving mode setting`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/nw_service/cpsms.html -.. _`Measuring current on nRF9160 DK`: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/hw_measure_current.html -.. _`Release Assistance Indication (RAI)`: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/nw_service/xrai.html - .. _`Electrical specification of nRF9160`: https://infocenter.nordicsemi.com/topic/ps_nrf9160/_tmp/alta.nRF9160/autodita/CURRENT/parameters.frontpage.html# .. _`nAN34`: https://infocenter.nordicsemi.com/pdf/nan_34.pdf @@ -629,13 +720,6 @@ .. _`Generating DFU packages`: https://infocenter.nordicsemi.com/topic/ug_nrfutil/UG/nrfutil/nrfutil_pkg.html .. _`DFU over a serial USB connection`: https://infocenter.nordicsemi.com/topic/ug_nrfutil/UG/nrfutil/nrfutil_dfu_serial_usb.html -.. _`nRF Thread Topology Monitor`: https://infocenter.nordicsemi.com/topic/ug_nrf_ttm/UG/nrf_ttm/ttm_introduction.html -.. _`nRF Sniffer for 802.15.4`: https://infocenter.nordicsemi.com/topic/ug_sniffer_802154/UG/sniffer_802154/intro_802154.html -.. _`Configuring Wireshark for Zigbee`: https://infocenter.nordicsemi.com/topic/ug_sniffer_802154/UG/sniffer_802154/configuring_sniffer_802154_zigbee.html - -.. _`Power Profiler Kit II (PPK2)`: https://infocenter.nordicsemi.com/topic/ug_ppk2/UG/ppk/PPK_user_guide_Intro.html -.. _`Install the Power Profiler app`: https://infocenter.nordicsemi.com/topic/ug_ppk2/UG/common/nrf_connect_app_installing.html -.. _`Using the Power Profiler app`: https://infocenter.nordicsemi.com/topic/ug_ppk2/UG/ppk/PPK_user_guide_Running_the_software.html .. _`anomaly 19`: https://infocenter.nordicsemi.com/topic/errata_nRF5340_EngA/ERR/nRF5340/EngineeringA/latest/anomaly_340_19.html .. _`nRF5 SDK Bootloader`: https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/lib_bootloader.html @@ -653,30 +737,29 @@ .. _`access port protection mechanism`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fdif.html&anchor=concept_udr_mns_1s -.. _`Electrical specification for nRF7002`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf7002%2Fchapters%2Felspec%2Fdoc%2Felectrical_specification.html - .. _`Wi-Fi Alliance Certification for nRF70 Series`: https://infocenter.nordicsemi.com/pdf/nwp_045.pdf .. _`Errata 254`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52840_Rev3%2FERR%2FnRF52840%2FRev3%2Flatest%2Fconfig_840_254.html - .. _`Errata 255`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52833_Rev2%2FERR%2FnRF52833%2FRev2%2Flatest%2Fconfig_833_255.html - .. _`Errata 256`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52820_Rev3%2FERR%2FnRF52820%2FRev3%2Flatest%2Fconfig_820_256.html - .. _`Errata 257`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52811_Rev2%2FERR%2FnRF52811%2FRev2%2Flatest%2Fconfig_811_257.html - .. _`Errata 117`: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF5340_Rev1%2FERR%2FnRF5340%2FRev1%2Flatest%2Fanomaly_340_117.html .. _`Unauthorized Thread Network Key Update (SA-2023-234) vulnerability`: https://infocenter.nordicsemi.com/pdf/SA-2023-234-v1_1.pdf - .. ### Source: academy.nordicsemi.com .. _`DevAcademy`: .. _`Nordic Developer Academy`: https://academy.nordicsemi.com/ .. _`nRF Connect SDK Fundamentals course`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/ +.. _`Installing nRF Connect SDK and VS Code`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/ + +.. _`nRF Connect SDK Intermediate course`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/ +.. _`Lesson 2 - Debugging and troubleshooting`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/ + .. _`Cellular IoT Fundamentals course`: https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/ +.. _`Power saving techniques`: https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/lessons/lesson-1-cellular-fundamentals/topic/lesson-1-power-saving-techniques/ .. _`Bluetooth LE Fundamentals course`: https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/ .. _`Wi-Fi Fundamentals course`: https://academy.nordicsemi.com/courses/wi-fi-fundamentals/ @@ -714,6 +797,8 @@ .. _`Bluetooth 5.4 DevZone blog`: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/whats-new-in-bluetooth-v5-4-an-overview +.. _`Certifying a cellular IoT device`: https://blog.nordicsemi.com/getconnected/certifying-a-cellular-iot-device/ + .. ### Source: www.segger.com .. _`J-Link Software and Documentation Pack`: https://www.segger.com/downloads/jlink @@ -778,7 +863,7 @@ .. _`OMA LwM2M Object and Resource Registry`: https://technical.openmobilealliance.org/OMNA/LwM2M/LwM2MRegistry.html -.. ### Source: wikipedia +.. ### Source: en.wikipedia.org .. _`GNSS`: https://en.wikipedia.org/wiki/Satellite_navigation .. _`GPS`: https://en.wikipedia.org/wiki/Global_Positioning_System @@ -824,7 +909,6 @@ .. _`Creating an Azure IoT Hub instance using the Azure portal`: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal .. _`Azure IoT Hub Device Provisioning Service (DPS)`: https://docs.microsoft.com/en-us/azure/iot-dps/ .. _`Set up an Azure IoT Hub Device Provisioning Service (DPS) instance`: https://docs.microsoft.com/en-us/azure/iot-dps/quick-setup-auto-provision -.. _`Creating Azure IoT Hub certificates`: https://docs.microsoft.com/en-us/azure/iot-hub/tutorial-x509-scripts .. _`Azure IoT Hub direct method`: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-direct-methods .. _`Azure IoT Hub MQTT protocol support`: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support .. _`Azure IoT Explorer`: https://docs.microsoft.com/en-us/azure/iot-pnp/howto-use-iot-explorer @@ -835,6 +919,8 @@ .. _`Add certificates to the DPS instance`: https://docs.microsoft.com/en-us/azure/iot-dps/how-to-verify-certificates .. _`Registering the device with Azure IoT Hub`: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal#register-a-new-device-in-the-iot-hub .. _`Azure IoT TLS: Critical changes`: https://techcommunity.microsoft.com/t5/internet-of-things-blog/azure-iot-tls-critical-changes-are-almost-here-and-why-you/ba-p/2393169 +.. _`Azure CLI`: https://learn.microsoft.com/en-us/cli/azure/install-azure-cli +.. _`Sign in with Azure CLI`: https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli .. _`Windows Hardware Lab Kit`: https://docs.microsoft.com/en-us/windows-hardware/test/hlk/ @@ -911,10 +997,6 @@ .. _`Matter Simple Setup for Thread Overview`: https://developer.amazon.com/docs/frustration-free-setup/matter-simple-setup-for-thread-overview.html .. _`Amazon Alexa integration with Matter`: https://developer.amazon.com/en-US/docs/alexa/smarthome/matter-support.html -.. ### Source: *.amazontrust.com - -.. _`Amazon Root CA 1`: https://www.amazontrust.com/repository/AmazonRootCA1.pem - .. ### Source: openthread.io .. _`OpenThread.io`: https://openthread.io/ @@ -972,6 +1054,7 @@ .. ### Source: cmake.org .. _`CMake documentation`: https://cmake.org/cmake/help/latest/ +.. _`CMake Tutorial`: https://cmake.org/cmake/help/latest/guide/tutorial/index.html#guide:CMake%20Tutorial .. _`VERBOSE`: https://cmake.org/cmake/help/latest/envvar/VERBOSE.html .. _`CMAKE_BUILD_PARALLEL_LEVEL`: https://cmake.org/cmake/help/latest/envvar/CMAKE_BUILD_PARALLEL_LEVEL.html .. _`CMAKE_BUILD_TYPE`: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html @@ -1001,7 +1084,7 @@ .. _`Nordic Semi Thingy:53 page`: https://docs.edgeimpulse.com/docs/development-platforms/officially-supported-mcu-targets/nordic-semi-thingy53 .. _`Nordic Semi nRF5340 DK page`: https://docs.edgeimpulse.com/docs/nordic-semi-nrf5340-dk -.. ### Source: memfault.com +.. ### Source: *.memfault.com .. _`Memfault`: https://memfault.com/ @@ -1016,20 +1099,17 @@ .. _`Memfault: Collecting Device Metrics`: https://docs.memfault.com/docs/embedded/metrics-api .. _`Memfault: Error Tracking with Trace Events`: https://docs.memfault.com/docs/embedded/trace-events/ .. _`Memfault Demo CLI`: https://docs.memfault.com/docs/mcu/demo-cli/ -.. _`Memfault Diagnostic GATT Service`: https://memfault.notion.site/Memfault-Diagnostic-GATT-Service-MDS-ffd5a430062649cd9bf6edbf64e2563b -.. _`Memfault WebBluetooth Client`: https://memfault.github.io/web-ble-example/ -.. _`Memfault WebBluetooth Client source code`: https://github.com/memfault/web-ble-example/blob/main/mds.js + .. _`Memfault Dashboards`: https://app.memfault.com .. _`Memfault debugging`: https://docs.memfault.com/docs/platform/introduction#debugging .. _`Memfault OTA`: https://docs.memfault.com/docs/platform/introduction#ota .. _`Memfault monitoring`: https://docs.memfault.com/docs/platform/introduction#metrics .. _`Memfault introduction`: https://docs.memfault.com/docs/platform/introduction -.. _`Memfault-SDK`: https://github.com/memfault/memfault-firmware-sdk + .. _`Memfault MCU Guide`: https://docs.memfault.com/docs/mcu/introduction .. _`Memfault: Reboot tracking`: https://docs.memfault.com/docs/mcu/reboot-reason-tracking .. _`Memfault: Coredumps`: https://docs.memfault.com/docs/mcu/coredumps - .. ### Source: *.nrfcloud.com .. _`nRF Cloud`: @@ -1042,6 +1122,8 @@ .. _`nRF Cloud Device ID`: https://docs.nrfcloud.com/Devices/Properties/DeviceId.html .. _`nRF Cloud Device Shadows`: https://docs.nrfcloud.com/Devices/Properties/Shadows.html .. _`nRF Cloud Security`: https://docs.nrfcloud.com/Devices/Security/Security.html +.. _`nRF Cloud Auto-onboarding`: https://docs.nrfcloud.com/Devices/Associations/Provisioning.html#auto-onboarding +.. _`nRF Cloud device claiming`: https://docs.nordicsemi.com/bundle/nrf-cloud/page/SecurityServices/ProvisioningService/ClaimingDevices/ClaimingDeviceOwnershipPortal.html .. _`nRF Cloud Preconnect Provisioning`: https://docs.nrfcloud.com/Devices/Associations/Provisioning.html#preconnect-provisioning .. _`nRF Cloud Just-In-Time-Provisioning`: https://docs.nrfcloud.com/Devices/Associations/Provisioning.html#just-in-time-provisioning .. _`nRF Cloud Onboarding`: @@ -1155,6 +1237,7 @@ .. ### Source: apple.com +.. _`macOS 14`: https://www.apple.com/macos/sonoma/ .. _`macOS 13`: https://www.apple.com/macos/ventura/ .. _`macOS 12`: https://www.apple.com/macos/monterey/ .. _`macOS 11`: https://support.apple.com/en-us/HT211896 @@ -1192,6 +1275,9 @@ .. _`Wi-Fi Certification`: https://www.wi-fi.org/certification .. _`QuickTrack Test Tool User Manual`: https://www.wi-fi.org/file-member/quicktrack-test-tool-user-manual .. _`QuickTrack Test Tool Platform Integration Guide`: https://www.wi-fi.org/file-member/quicktrack-test-tool-platform-integration-guide-v12 +.. _`QuickTrack New Product Application Training`: https://www.wi-fi.org/system/files/members/QuickTrack_New_Product_Application_Training_v1.2.pdf +.. _`QuickTrack Member Conformance Test Laboratory Setup`: https://www.wi-fi.org/system/files/members/QuickTrack_Member_Conformance_Test_Laboratory_Setup_v1.0.pdf +.. _`Wi-Fi_CERTIFIED_Derivative_Certifications_Overview`: https://www.wi-fi.org/system/files/Wi-Fi_CERTIFIED_Derivative_Certifications_Overview_v3.3.pdf .. _`Platform Intel Ax210 Integration Guide`: https://www.wi-fi.org/file-member/quicktrack-test-tool-platform-intel-ax210-station-integration-guide .. ### Source: avsystem.com & avsystem.cloud @@ -1201,7 +1287,7 @@ .. _`nRF Cloud integration with Coiote Device Management`: https://iotdevzone.avsystem.com/docs/Cloud_integrations/nRF_Cloud_Location_services/Configure_nRF_Cloud_integration/ .. _`Viewing device location in Coiote Device Management`: https://iotdevzone.avsystem.com/docs/Cloud_integrations/nRF_Cloud_Location_services/Configure_nRF_Cloud_integration/#view-device-location-in-coiote-dm .. _`Setting observations for an object`: https://iotdevzone.avsystem.com/docs/Coiote_IoT_DM/Quick_Start/Visualize_device_data/#set-observation-and-add-widget -.. _`nRF9160 Anjay integration`: https://iotdevzone.avsystem.com/docs/LwM2M_Client/Nordic/nRF9160/ +.. _`nRF9160 Anjay integration`: https://iotdevzone.avsystem.com/docs/LwM2M_Client/Nordic/nRF9160DK/ .. _`Thingy:91 integration`: https://iotdevzone.avsystem.com/docs/LwM2M_Client/Nordic/Thingy91/#thingy91 .. ### Source: mosquitto @@ -1210,30 +1296,51 @@ .. _`mosquitto.org server CA`: https://test.mosquitto.org/ssl/mosquitto.org.crt .. _`test.mosquitto.org`: https://test.mosquitto.org -.. ### visualstudio.com +.. ### Source: visualstudio.com .. _`nRF Connect for VS Code Extension Pack`: https://marketplace.visualstudio.com/items?itemName=nordic-semiconductor.nrf-connect-extension-pack .. _`VSMQTT`: https://marketplace.visualstudio.com/items?itemName=rpdswtk.vsmqtt .. _`Visual Studio Code download page`: https://code.visualstudio.com/download -.. ### python.org +.. ### Source: python.org .. _`Python virtual environments`: https://docs.python.org/3/library/venv.html .. _`Windows Python Path`: https://docs.python.org/3/using/windows.html#finding-the-python-executable .. _`Python's Path.glob`: https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob -.. ### Source: other (2 links or less from the same URL) +.. ### Source: youtube.com -.. _`MQTT getting started`: https://mqtt.org/getting-started/ +.. _`Developing Matter 1.0 products with nRF Connect SDK`: https://www.youtube.com/watch?v=9Ar13rMxGIk +.. _`Accelerate cellular product development`: https://youtu.be/b1YW1J4aUps +.. _`How nRF9160 enables cellular IoT asset tracking`: https://webinars.nordicsemi.com/how-nrf9160-enables-cellular-iot-4 -.. _`Memfault Diagnostic GATT Service`: https://memfault.notion.site/Memfault-Diagnostic-GATT-Service-MDS-ffd5a430062649cd9bf6edbf64e2563b +.. ### Source: onomondo.com -.. _`Developing Matter 1.0 products with nRF Connect SDK`: https://www.youtube.com/watch?v=9Ar13rMxGIk +.. _`Onomondo LTE-M coverage`: https://onomondo.com/product/coverage/lte-m-networks/ +.. _`Onomondo NB-IoT coverage`: https://onomondo.com/product/coverage/nb-iot-networks/ +.. _`Onomondo SoftSIM integration with the nRF91 Series`: https://help.onomondo.com/en/how-to-integrate-the-onomondo-softsim-with-the-nrf9160-from-nordic-semiconductor -.. _`iBasis IoT network coverage`: https://ibasis.com/solutions/iot-connectivity/network-coverage/ +.. ### Source: bosch-sensortec.com .. _`BME680`: https://www.bosch-sensortec.com/products/environmental-sensors/gas-sensors/bme680/ .. _`Bosch BSEC`: https://www.bosch-sensortec.com/software-tools/software/bsec/ +.. _`BSEC license`: https://www.bosch-sensortec.com/media/boschsensortec/downloads/software/bme688_development_software/2023_04/license_terms_bme688_bme680_bsec.pdf + +.. ### Source: wireshark.org + +.. _`Wireshark`: https://www.wireshark.org +.. _`Wireshark with Lua`: https://wiki.wireshark.org/Lua +.. _`Wireshark Unix Build setup`: https://www.wireshark.org/docs/wsdg_html_chunked/ChapterSetup.html#ChSetupUNIX + +.. ### Source: other (2 links or less from the same URL) + +.. _`Amazon Root CA 1`: https://www.amazontrust.com/repository/AmazonRootCA1.pem + +.. _`Memfault Diagnostic GATT Service`: https://memfault.notion.site/Memfault-Diagnostic-GATT-Service-MDS-ffd5a430062649cd9bf6edbf64e2563b + +.. _`MQTT getting started`: https://mqtt.org/getting-started/ + +.. _`iBasis IoT network coverage`: https://ibasis.com/solutions/iot-connectivity/network-coverage/ .. _`ADXL362`: https://www.analog.com/en/products/adxl362.html#product-overview .. _`ADXL372`: https://www.analog.com/en/products/adxl372.html#product-overview @@ -1261,7 +1368,6 @@ .. _`Azure Portal`: https://portal.azure.com/ - .. _`Verizon's Thingspace`: https://thingspace.verizon.com .. _`Verizon's Get certified program`: https://opendevelopment.verizonwireless.com/get-certified @@ -1286,7 +1392,6 @@ .. _`POSIX Programmer's Manual`: https://man7.org/linux/man-pages/dir_section_3.html .. _`LwM2M`: https://omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/ .. _`IPSO objects`: https://omaspecworks.org/develop-with-oma-specworks/ipso-smart-objects/ -.. _`raw XML`: https://raw.githubusercontent.com/OpenMobileAlliance/lwm2m-registry/prod/version_history/3300-1_0.xml .. _`DLPTest.com`: https://dlptest.com/ftp-test/ @@ -1309,15 +1414,12 @@ .. _`BH1749NUC-E`: https://fscdn.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1749nuc-e.pdf - - .. _`CMock`: https://www.throwtheswitch.org/cmock .. _`Unity`: https://www.throwtheswitch.org/unity .. _`NMEA`: https://www.gpsworld.com/what-exactly-is-gps-nmea-data/ .. _`Baltimore CyberTrust Root certificate`: https://cacerts.digicert.com/BaltimoreCyberTrustRoot.crt.pem - .. _`DigiCert Global Root G2`: https://cacerts.digicert.com/DigiCertGlobalRootG2.crt.pem .. _`SKY66112-11 page`: https://www.skyworksinc.com/en/Products/Front-end-Modules/SKY66112-11 @@ -1347,10 +1449,6 @@ .. _`dfu-util tool`: http://dfu-util.sourceforge.net/ -.. _`Termite`: https://www.compuphase.com/software_termite.htm - -.. _`Teraterm`: https://ttssh2.osdn.jp/index.html.en - .. _`GNU Project Debugger`: https://www.sourceware.org/gdb/ .. _`SIGMA`: https://link.springer.com/chapter/10.1007/978-3-540-45146-4_24 @@ -1361,12 +1459,62 @@ .. _`Samsung SmartThings integration with Matter`: https://support.smartthings.com/hc/en-us/articles/11219700390804-SmartThings-x-Matter-Integration- -.. _`Wireshark`: https://www.wireshark.org +.. _`Community Best Practice for Copyright Notice`: https://www.linuxfoundation.org/blog/copyright-notices-in-open-source-software-projects/ -.. _`Amazon license`: https://raw.githubusercontent.com/nrfconnect/sdk-sidewalk/main/LICENSE.txt +.. _`HTTPie`: https://httpie.io/ -.. _`Sidewalk documentation`: https://nrfconnect.github.io/sdk-sidewalk/ +.. _`Devicetree Specification`: https://www.devicetree.org/ -.. _`Setting up the SDK for Amazon Sidewalk`: https://nrfconnect.github.io/sdk-sidewalk/setting_up_sidewalk_environment/setting_up_sdk.html +.. _`Mobile IoT deployment map`: https://www.gsma.com/iot/deployment-map/ -.. _`Community Best Practice for Copyright Notice`: https://www.linuxfoundation.org/blog/copyright-notices-in-open-source-software-projects/ +.. _`CoreMark®`: https://www.eembc.org/coremark/ + +.. ### Temp: nRF54H and nRF54L related links, repositories, and documents + +.. _`nrf-regtool`: https://github.com/nrfconnect/nrf-regtool/ +.. _`UICR overlay`: https://github.com/nrfconnect/sdk-nrf-next/tree/haltium-ncs/applications/machine_learning/configuration/nrf54h20dk_nrf54h20_cpuapp%40soc1/uicr +.. _`nRF54H20 common SoC files`: https://github.com/nrfconnect/sdk-ic-next/tree/haltium/soc +.. _`ARM cores configuration files`: https://github.com/nrfconnect/sdk-ic-next/tree/haltium/boards/arm/nrf54h20dk_nrf54h20 +.. _`Risc-V cores configuration files`: https://github.com/nrfconnect/sdk-ic-next/tree/haltium/boards/riscv/nrf54h20dk_nrf54h20 +.. _`nRF54H20 Objective Product Specification 0.3`: https://res.developer.nordicsemi.com/res/nrf54H20/OPS/nRF54H20_OPS_v0.3.pdf +.. _`nRF54H20 Objective Product Specification 0.3.1`: https://res.developer.nordicsemi.com/res/nrf54H20/OPS/nRF54H20_OPS_v0.3.1.pdf + +.. _`Introduction to nRF54H20`: https://res.developer.nordicsemi.com/res/nrf54H20/intro/Introduction%20to%20nRF54H20%20v1_0_1.pdf +.. _`nRF54H20 prototype difference`: https://res.developer.nordicsemi.com/res/nrf54H20/other/nRF54H20_proto_diff.pdf + +.. _`BICR register's PDF file`: https://res.developer.nordicsemi.com/res/nrf54H20/BICR/nRF54H20_BICR_0_11_0.pdf +.. _`nRF Command Line Tools 10.22.1`: https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download + +.. _`documentation page on Github Authentication`: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github +.. _`documentation page on authentication methods`: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github +.. _`ssh-agent`: https://www.ssh.com/ssh/agent +.. _`Connecting to GitHub with SSH`: https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh +.. _`SSH-based authentication`: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent +.. _`git-credential-store`: https://git-scm.com/docs/git-credential-store#_examples +.. _`git-credential-cache`: https://git-scm.com/docs/git-credential-cache +.. _`personal access token`: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token +.. _`Git Credential Manager`: https://github.com/git-ecosystem/git-credential-manager +.. _`Personal Access Token (PAT)`: https://github.com/settings/tokens +.. _`Homebrew`: https://brew.sh/ +.. _`sdk-find-my-next repository`: https://github.com/nrfconnect/sdk-find-my-next + +.. _`Serial Terminal from nRF Connect for Desktop`: https://infocenter.nordicsemi.com/topic/ug_serial_terminal/UG/serial_terminal/intro.html + +.. _`10.23.3_ec 64-bit Windows, executable`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nRF-Command-Line-Tools-10.23.3-x64.exe + +.. _`10.23.3_ec x86 system, deb format`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools_10.23.3_amd64.deb +.. _`10.23.3_ec x86 system, RPM`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3-1.x86_64.rpm +.. _`10.23.3_ec x86 system, tar archive`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3_Linux-amd64.tar.gz + +.. _`10.23.3_ec ARM64 system, deb format`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools_10.23.3_arm64.deb +.. _`10.23.3_ec ARM64 system, RPM`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3-1.arm64.rpm +.. _`10.23.3_ec ARM64 system, tar archive`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3_Linux-arm64.tar.gz + +.. _`10.23.3_ec ARMHF system, zip archive`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3-armhf-linux.zip + +.. _`10.23.3_ec macOS, zip archive`: https://res.developer.nordicsemi.com/res/nrf-command-line-tools-10.23.3/nrf-command-line-tools-10.23.3-osx.zip + +.. _`Git for Windows`: https://git-scm.com/download/win +.. _`nRF Terminal documentation`: https://nrfconnect.github.io/vscode-nrf-connect/terminal/nrfterminal.html + +.. _`nRF7002 EK`: https://infocenter.nordicsemi.com/topic/ug_nrf7002_ek/UG/nrf7002_EK/intro.html diff --git a/doc/nrf/protocols.rst b/doc/nrf/protocols.rst index 56a66f9d35b..47a2967240e 100644 --- a/doc/nrf/protocols.rst +++ b/doc/nrf/protocols.rst @@ -14,6 +14,7 @@ They introduce you to concepts that are important to work with the protocol and protocols/bt/index protocols/esb/index protocols/gazell/index + protocols/lte/index protocols/matter/index protocols/multiprotocol/index protocols/nfc/index diff --git a/doc/nrf/protocols/bt/ble/index.rst b/doc/nrf/protocols/bt/ble/index.rst index e29f96a540e..445c6d1f10d 100644 --- a/doc/nrf/protocols/bt/ble/index.rst +++ b/doc/nrf/protocols/bt/ble/index.rst @@ -59,8 +59,7 @@ Usage in samples **************** Most :ref:`Bluetooth LE samples ` in the |NCS|, including the :ref:`bt_mesh_samples`, can use either Bluetooth LE Controller. -An exception is the :ref:`ble_llpm` sample, which requires the SoftDevice Controller that supports LLPM. -There is also a separate controller for the :ref:`nrf53_audio_app` application, namely the :ref:`lib_bt_ll_acs_nrf53_readme`. +Exceptions are the :ref:`ble_llpm` sample, which requires the SoftDevice Controller that supports LLPM, and the :ref:`nrf53_audio_app`, which require the SoftDevice Controller that supports :ref:`LE Isochronous Channels `. By default, all samples are currently configured to use SoftDevice Controller. To use the Zephyr Bluetooth LE Controller instead, set :kconfig:option:`CONFIG_BT_LL_SW_SPLIT` to ``y`` in the :file:`prj.conf` file (see :ref:`configure_application`) and make sure to build from a clean build directory. diff --git a/doc/nrf/protocols/bt/bt_mesh/architecture.rst b/doc/nrf/protocols/bt/bt_mesh/architecture.rst index 415200c2754..28c909edb69 100644 --- a/doc/nrf/protocols/bt/bt_mesh/architecture.rst +++ b/doc/nrf/protocols/bt/bt_mesh/architecture.rst @@ -7,7 +7,7 @@ Bluetooth Mesh stack architecture :local: :depth: 2 -The Bluetooth® mesh stack in |NCS| is an extension of the Zephyr Bluetooth® mesh stack. +The Bluetooth® Mesh stack in |NCS| is an extension of the Zephyr Bluetooth Mesh stack. The Zephyr Bluetooth Mesh stack implements the Bluetooth Mesh profile specification (see :ref:`zephyr:bluetooth_mesh`), while |NCS| provides additional model implementations from the Bluetooth Mesh model specification on top of the :ref:`zephyr:bluetooth_mesh_access` API. .. figure:: images/bt_mesh_basic_architecture.svg diff --git a/doc/nrf/protocols/bt/bt_mesh/concepts.rst b/doc/nrf/protocols/bt/bt_mesh/concepts.rst index 611ce619690..e4c9d26e058 100644 --- a/doc/nrf/protocols/bt/bt_mesh/concepts.rst +++ b/doc/nrf/protocols/bt/bt_mesh/concepts.rst @@ -7,7 +7,7 @@ Bluetooth Mesh concepts :local: :depth: 2 -Bluetooth® mesh is a profile specification developed and published by the Bluetooth® Special Interest Group (SIG). +Bluetooth® Mesh is a profile specification developed and published by the Bluetooth Special Interest Group (SIG). This document explains the basic concepts of the Bluetooth Mesh and gives an overview of the operation and capabilities of the profile, as well as the life cycle of a mesh device. For more information about the |NCS| implementation of the Bluetooth Mesh, see :ref:`Bluetooth Mesh architecture documentation `. @@ -266,7 +266,7 @@ The Bluetooth Mesh profile specification defines a range of out-of-band authenti * Blinking of lights * Output and input of passphrases -* Static authentication against a pre-shared key +* Static authentication against a pre-shared key (PSK) To secure the provisioning procedure, elliptic curve Diffie-Helman (ECDH) public key cryptography is used. After a device has been provisioned, it is part of the network and all its messages are considered authenticated. diff --git a/doc/nrf/protocols/bt/bt_mesh/configuring.rst b/doc/nrf/protocols/bt/bt_mesh/configuring.rst index 4fa2a7bb23f..7eaf6d10a51 100644 --- a/doc/nrf/protocols/bt/bt_mesh/configuring.rst +++ b/doc/nrf/protocols/bt/bt_mesh/configuring.rst @@ -7,12 +7,17 @@ Configuring Bluetooth Mesh in |NCS| :local: :depth: 2 -The Bluetooth® mesh support is controlled by :kconfig:option:`CONFIG_BT_MESH`, which depends on the following configuration options: +The Bluetooth® Mesh support is controlled by :kconfig:option:`CONFIG_BT_MESH`, which depends on the following configuration options: * :kconfig:option:`CONFIG_BT` - Enables the Bluetooth subsystem. * :kconfig:option:`CONFIG_BT_OBSERVER` - Enables the Bluetooth Observer role. * :kconfig:option:`CONFIG_BT_PERIPHERAL` - Enables the Bluetooth Peripheral role. +When the Bluetooth LE Controller is located on a separate image (like on the :ref:`zephyr:nrf5340dk_nrf5340` and :ref:`zephyr:thingy53_nrf5340` boards), the following configuration must be applied to the Bluetooth LE Controller configuration: + +* :kconfig:option:`CONFIG_BT_EXT_ADV` =y. +* :kconfig:option:`CONFIG_BT_EXT_ADV_MAX_ADV_SET` =5. + Optional features configuration ******************************* @@ -172,3 +177,73 @@ The following configuration options are relevant when using the LPN feature: * Reducing the Node ID advertisement timeout decreases the period where the device consumes power for advertising. * :kconfig:option:`CONFIG_BT_MESH_NODE_ID_TIMEOUT` =30. + +Persistent storage +------------------ + +Zephyr's Mesh implementation has been designed to use the :ref:`settings ` subsystem to store internal states and options in the :ref:`persistent storage `. +The settings subsystem can be used with different backends. +Bluetooth Mesh is configured with the :ref:`non-volatile storage (NVS) ` as the settings backend. + +Using the settings subsystem based on NVS can in some cases result in a significant store time increase. +In a worst case scenario, the store time can be up to several minutes. +This can for example happen when storing a large size replay protection list. +It is recommended to configure the settings subsystem's internal caches to improve the performance. + +NVS lookup cache reduces the number of search loops within NVS' application table. + +* :kconfig:option:`CONFIG_NVS_LOOKUP_CACHE`. + +The Settings NVS name cache reduces the number of search loops of internal parameter identifiers, keeping them in memory. + +* :kconfig:option:`CONFIG_SETTINGS_NVS_NAME_CACHE`. + +The size of the Settings NVS name cache, :kconfig:option:`CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE`, is recommended to be at least equal to the number of settings entries the device is expected to store. + +The Bluetooth Mesh stack stores the following data persistently: + +* Network information (primary address and device key) +* Configuration parameters (supported features, default TTL, network transmit and relay retransmit parameters) +* IV index +* Sequence number +* Heartbeat publication information +* Application key(s) (the amount of entries is controlled by :kconfig:option:`CONFIG_BT_MESH_APP_KEY_COUNT`) +* Network key(s) (the amount of entries is controlled by :kconfig:option:`CONFIG_BT_MESH_SUBNET_COUNT`) +* Label UUIDs for virtual addressing (the amount of entries is controlled by :kconfig:option:`CONFIG_BT_MESH_LABEL_COUNT`) +* RPL entries (the RPL size is controlled by :kconfig:option:`CONFIG_BT_MESH_CRPL`) + +The following data is stored for each model by the Bluetooth Mesh stack: + +* Model subscription state +* Model publication state +* Bound application key(s) +* Subscription list for group addresses +* Subscription list for virtual addresses +* Label UUIDs the model is subscribed to +* Model-specific data + +Model data stored persistently can be found under the ``Persistent storage`` section of the corresponding model documentation. + +Using the :ref:`bluetooth_mesh_sensor_server` sample as an example, configured according to the sample's :ref:`configuration guide `, results in the following list of possible entries (entries mentioned above are not included unless specifying the amount of entries): + +* 32 RPL entries - since the default Networked Lighting Control (NLC) configuration is used (:kconfig:option:`CONFIG_BT_MESH_NLC_PERF_DEFAULT` is set), the RPL size is 32. +* Application keys - three keys are used. +* Bound application keys - each of the three Sensor Server and Sensor Setup Server models has one bound application key. +* Network keys - only one key is used. +* Model subscriptions - each of the three Sensor Server and Sensor Setup Server models subscribes to a group address. +* Model publication information - each of the three Sensor Server models publishes to a group address. +* Virtual addressing is not used. +* :ref:`Sensor Server model data ` - each of the three Sensor Server models stores the following data: + + * Minimum interval + * Delta thresholds + * Fast period divisor + * Fast cadence range + +* The following values are stored in the sample: + + * Temperature range + * Presence motion threshold + * Ambient light level gain + +Adding up all entries, it is worth setting the cache size to minimum 71. diff --git a/doc/nrf/protocols/bt/bt_mesh/dfu_over_bt_mesh.rst b/doc/nrf/protocols/bt/bt_mesh/dfu_over_bt_mesh.rst index 29ec4cb4fde..b5324be60f3 100644 --- a/doc/nrf/protocols/bt/bt_mesh/dfu_over_bt_mesh.rst +++ b/doc/nrf/protocols/bt/bt_mesh/dfu_over_bt_mesh.rst @@ -26,7 +26,7 @@ For the complete list of commands, see the :ref:`zephyr:bluetooth_mesh_shell_dfd The commands can be executed in two ways: -* Through the shell management subsystem of MCU manager (for example, using the nRF Connect Device Manager mobile application or :ref:`Mcumgr command-line tool `). +* Through the shell management subsystem of MCU manager (for example, using the nRF Connect Device Manager mobile application on Android or :ref:`Mcumgr command-line tool `). * By accessing the :ref:`zephyr:shell_api` module over UART. Provisioning and configuring the devices @@ -182,8 +182,78 @@ To bring a stalled Target node to idle state, use the ``mesh models dfu cli canc .. _bluetooth_mesh_dfu_eval_md: -Composing the firmware metadata -******************************* +Generating the firmware metadata +******************************** + +There are two ways to generate the required DFU metadata: + + * Automated generation using the DFU metadata extraction script integrated in the |NCS| build system. + * Manual generation by using shell commands. + +Using the DFU metadata extraction script is the most efficient way of generating the required DFU metadata. + +Automated metadata generation +============================= + +By enabling the :kconfig:option:`CONFIG_BT_MESH_DFU_METADATA_ON_BUILD` option in the application, the metadata will be automatically parsed from the ``.elf`` and ``.config`` files. +The parsed data is stored in the :file:`ble_mesh_metadata.json` file. +The file is placed in the :file:`dfu_application.zip` archive in the build folder of the application. +Additionally, the metadata string required by the ``mesh models dfu slot add`` command will be printed in the command line window when the application is built:: + + Bluetooth Mesh Composition metadata generated: + Encoded metadata: 020000000100000094cf24017c26f3710100 + Full metadata written to: APPLICATION_FOLDER\build\zephyr\dfu_application.zip + +.. note:: + It is required that the Composition Data is declared with the ``const`` qualifier. + If the application contains more than one Composition Data structure (for example, when the structure to be used is picked at runtime), the script will not print any encoded metadata. + In this case, use the JSON file to find the encoded metadata matching the Composition Data to be used by the device after the update. + Additionally, the script is hardcoded to produce a metadata string where the firmware is targeted for the application core. + +A separate west command can be utilized to print the metadata to the console, given that it is already generated by the build system. +This gives the user easy access to this information, without having to enter the ``.json`` file in the build folder or to rebuild the application:: + + west build -t ble_mesh_dfu_metadata + +For this particular example, the following output is generated: + + .. toggle:: + + .. code-block:: console + + { + "sign_version": { + "major": 2, + "minor": 0, + "revision": 0, + "build_number": 0 + }, + "binary_size": 241236, + "composition_data": { + "cid": 89, + "pid": 0, + "vid": 0, + "crpl": 10, + "features": 7, + "elements": [ + { + "location": 1, + "sig_models": [ + 0, + 2, + 48962, + 48964 + ], + "vendor_models": [] + } + ] + }, + "composition_hash": "0x71f3267c", + "encoded_metadata": "020000000100000094cf24017c26f3710100" + } + +Manual metadata generation +========================== The Bluetooth Mesh DFU subsystem provides a set of shell commands that can be used to compose a firmware metadata. The format of metadata is defined in the :c:struct:`bt_mesh_dfu_metadata` structure. @@ -201,7 +271,7 @@ For example, for :ref:`ble_mesh_dfu_target` sample, which has only one element c mesh models dfu metadata comp-elem-add 1 4 0 0x0000 0x0002 0xBF42 0xBF44 .. note:: - In case of any mistakes being done during the enconding of the Composition Data, use the ``mesh models dfu metadata comp-clear`` command to clear the cached value, then start composing the metadata from the beginning. + In case of any mistakes during the encoding of the Composition Data, use the ``mesh models dfu metadata comp-clear`` command to clear the cached value, then start composing the metadata from the beginning. When all elements are added, generate a hash of the Composition Data using the ``mesh models dfu metadata comp-hash-get`` shell command. For example, using the inputs from the commands above, the output of this command should be the following:: diff --git a/doc/nrf/protocols/bt/bt_mesh/fota.rst b/doc/nrf/protocols/bt/bt_mesh/fota.rst index f750f11230e..ae7e2b9bac2 100644 --- a/doc/nrf/protocols/bt/bt_mesh/fota.rst +++ b/doc/nrf/protocols/bt/bt_mesh/fota.rst @@ -3,10 +3,10 @@ Performing Device Firmware Updates (DFU) in Bluetooth Mesh ########################################################## -The |NCS| supports two DFU methods when updating your firmware over-the-air (FOTA) for your Bluetooth Mesh devices and applications. +The |NCS| supports two DFU methods when updating your firmware over-the-air (FOTA) for your Bluetooth® Mesh devices and applications. -* DFU over Bluetooth® mesh using the Zephyr Bluetooth Mesh DFU subsystem that implements the Mesh Device Firmware Update Model specification version 1.0 and Mesh Binary Large Object Transfer Model specification version 1.0. -* Point-to-point DFU over Bluetooth® Low Energy using the MCUmgr subsystem and the Simple Management Protocol (SMP). +* DFU over Bluetooth Mesh using the Zephyr Bluetooth Mesh DFU subsystem that implements the Mesh Device Firmware Update Model specification version 1.0 and Mesh Binary Large Object Transfer Model specification version 1.0. +* Point-to-point DFU over Bluetooth Low Energy using the MCUmgr subsystem and the Simple Management Protocol (SMP). .. toctree:: :maxdepth: 1 diff --git a/doc/nrf/protocols/bt/bt_mesh/index.rst b/doc/nrf/protocols/bt/bt_mesh/index.rst index 82529ebc9c4..d76ef74ba30 100644 --- a/doc/nrf/protocols/bt/bt_mesh/index.rst +++ b/doc/nrf/protocols/bt/bt_mesh/index.rst @@ -3,10 +3,10 @@ Bluetooth Mesh ############## -The |NCS| provides support for developing applications using the Bluetooth® mesh protocol. +The |NCS| provides support for developing applications using the Bluetooth® Mesh protocol. The support is based on Zephyr's :ref:`bluetooth_mesh` implementation. -The `Bluetooth Mesh profile specification`_ is developed and published by the Bluetooth® Special Interest Group (SIG). +The `Bluetooth Mesh profile specification`_ is developed and published by the Bluetooth Special Interest Group (SIG). It allows one-to-one, one-to-many, and many-to-many communication, using the Bluetooth LE protocol to exchange messages between the nodes on the network. All nodes in a Bluetooth Mesh network can communicate with each other, as long as there is a chain of nodes between them to relay the messages. The messages are encrypted with two layers of 128-bit AES-CCM encryption, allowing secure communication between thousands of devices. diff --git a/doc/nrf/protocols/bt/bt_mesh/model_config_app.rst b/doc/nrf/protocols/bt/bt_mesh/model_config_app.rst index 654ab239bd5..63481ffabca 100644 --- a/doc/nrf/protocols/bt/bt_mesh/model_config_app.rst +++ b/doc/nrf/protocols/bt/bt_mesh/model_config_app.rst @@ -7,7 +7,7 @@ Configuring mesh models using the nRF Mesh mobile app :local: :depth: 2 -The Bluetooth® mesh :ref:`samples ` use the nRF Mesh mobile app to perform provisioning and configuration. +The Bluetooth® Mesh :ref:`samples ` use the nRF Mesh mobile app to perform provisioning and configuration. Binding a model to an application key ************************************* diff --git a/doc/nrf/protocols/bt/bt_mesh/node_removal.rst b/doc/nrf/protocols/bt/bt_mesh/node_removal.rst index 2651dd58c51..0dd33346906 100644 --- a/doc/nrf/protocols/bt/bt_mesh/node_removal.rst +++ b/doc/nrf/protocols/bt/bt_mesh/node_removal.rst @@ -7,7 +7,7 @@ Removing a node from a mesh network :local: :depth: 2 -In certain circumstances, a need may arise to remove a node from a Bluetooth® mesh network. +In certain circumstances, a need may arise to remove a node from a Bluetooth® Mesh network. This can be done by unprovisioning the node using the Config Node Reset message. Though the unprovisioning of the node is a straightforward procedure, some additional steps need to be taken to maintain the security of the network. diff --git a/doc/nrf/protocols/bt/bt_mesh/supported_features.rst b/doc/nrf/protocols/bt/bt_mesh/supported_features.rst index 829f0c325f1..805aa4ec2a8 100644 --- a/doc/nrf/protocols/bt/bt_mesh/supported_features.rst +++ b/doc/nrf/protocols/bt/bt_mesh/supported_features.rst @@ -3,7 +3,7 @@ Supported Bluetooth Mesh features ################################# -The Bluetooth® mesh in |NCS| supports all mandatory features of the `Bluetooth Mesh profile specification`_ and the `Bluetooth Mesh model specification`_, as well as most of the optional features. +The Bluetooth® Mesh in |NCS| supports all mandatory features of the `Bluetooth Mesh profile specification`_ and the `Bluetooth Mesh model specification`_, as well as most of the optional features. The following features are supported by Zephyr's :ref:`zephyr:bluetooth_mesh`: diff --git a/doc/nrf/protocols/bt/bt_mesh/vendor_model/dev_overview.rst b/doc/nrf/protocols/bt/bt_mesh/vendor_model/dev_overview.rst index 3c84d26cc26..33063a20493 100644 --- a/doc/nrf/protocols/bt/bt_mesh/vendor_model/dev_overview.rst +++ b/doc/nrf/protocols/bt/bt_mesh/vendor_model/dev_overview.rst @@ -7,7 +7,7 @@ Vendor model development overview :local: :depth: 2 -To implement a new Bluetooth® mesh model, apply the steps described in this step-by-step model development process overview. +To implement a new Bluetooth® Mesh model, apply the steps described in this step-by-step model development process overview. Defining a model identifier *************************** @@ -22,7 +22,7 @@ As defined by the `Bluetooth Mesh profile specification`_, the vendor model iden #define YOUR_COMPANY_ID 0x1234 #define YOUR_MODEL_ID 0x5678 -The Company ID must be registered with the Bluetooth® Special Interest Group (SIG), and the vendor owning the Company ID may freely allocate the model IDs for its Company ID. +The Company ID must be registered with the Bluetooth Special Interest Group (SIG), and the vendor owning the Company ID may freely allocate the model IDs for its Company ID. See `Bluetooth SIG company identifiers`_ for a list of Company IDs. Adding the model to the node composition data diff --git a/doc/nrf/protocols/bt/bt_mesh/vendor_model/index.rst b/doc/nrf/protocols/bt/bt_mesh/vendor_model/index.rst index 24fe741776b..196897b873f 100644 --- a/doc/nrf/protocols/bt/bt_mesh/vendor_model/index.rst +++ b/doc/nrf/protocols/bt/bt_mesh/vendor_model/index.rst @@ -3,7 +3,7 @@ Creating a new model #################### -You may create your own vendor-specific models for Bluetooth® mesh. +You may create your own vendor-specific models for Bluetooth® Mesh. These will enable your devices to provide custom behavior not covered by the already defined standard models. The following sections describe the basics of creating new models for the Bluetooth Mesh in |NCS|, based on the concepts and principles defined in :ref:`mesh_concepts` and :ref:`Access API `. It is recommended that you have read and understood these concepts and principles, before proceeding with the model development. diff --git a/doc/nrf/protocols/bt/bt_qualification/index.rst b/doc/nrf/protocols/bt/bt_qualification/index.rst index 1f85394398e..a4c577105bf 100644 --- a/doc/nrf/protocols/bt/bt_qualification/index.rst +++ b/doc/nrf/protocols/bt/bt_qualification/index.rst @@ -119,7 +119,7 @@ Use the listing search in the following cases: Matter certification by inheritance *********************************** -Bluetooth QDIDs may be further used to obtain the Matter certification by inheritence. +Bluetooth QDIDs may be further used to obtain the Matter certification by inheritance. See the :ref:`ug_matter_device_certification_reqs_dependent` section for details. Support diff --git a/doc/nrf/protocols/esb/images/esb_fig2_ptx_trans_ok.svg b/doc/nrf/protocols/esb/images/esb_fig2_ptx_trans_ok.svg index 3629268418a..487355e2eb8 100644 --- a/doc/nrf/protocols/esb/images/esb_fig2_ptx_trans_ok.svg +++ b/doc/nrf/protocols/esb/images/esb_fig2_ptx_trans_ok.svg @@ -7,14 +7,14 @@ @@ -35,254 +36,257 @@ - + - + - + - + Page-1 - - Sheet.335 - PTX operation - - PTX operation - - Rectangle.336 - - - - Rectangle.337 - - - - Sheet.339 - PRX operation - - PRX operation - - Rectangle.340 - - - - s.free.431 - Listen - - Listen - - s.free.432 - Listen - - Listen - - Sheet.433 - - - - Sheet.434 - - - - s.435 - Send packet - - Send packet - - s.331 - Send ACK - - Send ACK - - s.437 - Receive packet - - Receive packet - - Rectangle.391 - - - - Rectangle.392 - - - - s.394 - Resend packet - - Resend packet - - Rectangle.395 - - - - Rectangle.396 - - - - s.398 - Resend packet - - Resend packet - - Rectangle.399 - - - - s.free.401 - Listen - - Listen - - s.402 - Send ACK - - Send ACK - - s.447 - Receive packet - - Receive packet - - Sheet.448 - - - - Sheet.449 - - - - Rectangle.450 - - - - Rectangle.400 - - - - Rectangle.410 - - - - s.free.411 - Wait for ACK - - Wait for ACK - - s.free.412 - Wait for ACK - - Wait for ACK - - Deletion - - Sheet.456 - - + + Sheet.486 + + Sheet.335 + PTX operation + + PTX operation + + Rectangle.336 + - - - Sheet.457 - - - - Deletion.418 - - Sheet.459 - - + + Rectangle.337 + - - - Deletion.422 - - Sheet.461 - - + + Sheet.339 + PRX operation + + PRX operation + + Rectangle.340 + + + s.free.431 + Listen + + Listen + + s.free.432 + Listen + + Listen + + Sheet.433 + + + + Sheet.434 + + + + s.435 + Send packet + + Send packet + + s.331 + Send ACK + + Send ACK + + s.437 + Receive packet + + Receive packet + + Rectangle.391 + + + + Rectangle.392 + + + + s.394 + Resend packet + + Resend packet + + Rectangle.395 + + + + Rectangle.396 + + + + s.398 + Resend packet + + Resend packet + + Rectangle.399 + + + + s.free.401 + Listen + + Listen + + s.402 + Send ACK + + Send ACK + + s.447 + Receive packet + + Receive packet + + Sheet.448 + + + + Sheet.449 + + + + Rectangle.450 + + + + Rectangle.400 + + + + Rectangle.410 + + + + s.free.411 + Wait for ACK + + Wait for ACK + + s.free.412 + Wait for ACK + + Wait for ACK + + Deletion + + Sheet.456 + + + + + + Sheet.457 + + + + Deletion.418 + + Sheet.459 + + + + + + Deletion.422 + + Sheet.461 + + + + + + Sheet.462 + + + + s.free.450 + Wait for ACK + + Wait for ACK + + Sheet.334 + + + + Sheet.338 + + + + Nordic Middle Grey.466 + Event with event ID NRF_ESB_EVENT_RX_RECEIVED + + Event with event ID NRF_ESB_EVENT_RX_RECEIVED + + Dynamic connector.467 + + + + Nordic Middle Grey.469 + Packet recognized as retransmit attempt and discarded by PRX. + + Packet recognized as retransmit attempt and discarded by PRX. + + Dynamic connector.470 + + + + Nordic Middle Grey.472 + Initial packet + + Initial packet + + Dynamic connector.473 + + + + Nordic Middle Grey.475 + Retransmit attempt 1 + + Retransmit attempt 1 + + Dynamic connector.478 + + + + Nordic Middle Grey.479 + Retransmit attempt 2 + + Retransmit attempt 2 + + Nordic Middle Grey.481 + Event with event ID NRF_ESB_EVENT_TX_FAILED + + Event with event ID NRF_ESB_EVENT_TX_FAILED + + Dynamic connector.483 + + + + Dynamic connector.484 + + + + Sheet.485 + Retransmission delay + + Retransmission delay - - Sheet.462 - - - - s.free.450 - Wait for ACK - - Wait for ACK - - Sheet.334 - - - - Sheet.338 - - - - Nordic Middle Grey.466 - Event with event ID NRF_ESB_EVENT_RX_RECEIVED - - Event with event ID NRF_ESB_EVENT_RX_RECEIVED - - Dynamic connector.467 - - - - Nordic Middle Grey.469 - Packet recognized as retransmit attempt and discarded by PRX. - - Packet recognized as retransmit attempt and discarded by PRX. - - Dynamic connector.470 - - - - Nordic Middle Grey.472 - Initial packet - - Initial packet - - Dynamic connector.473 - - - - Nordic Middle Grey.475 - Retransmit attempt 1 - - Retransmit attempt 1 - - Dynamic connector.478 - - - - Nordic Middle Grey.479 - Retransmit attempt 2 - - Retransmit attempt 2 - - Nordic Middle Grey.481 - Event with event ID NRF_ESB_EVENT_TX_FAILED - - Event with event ID NRF_ESB_EVENT_TX_FAILED - - Dynamic connector.483 - - - - Dynamic connector.484 - - - - Sheet.485 - Retransmission delay - - Retransmission delay diff --git a/doc/nrf/protocols/esb/index.rst b/doc/nrf/protocols/esb/index.rst index 4fe6a61cbcf..30c41694b4c 100644 --- a/doc/nrf/protocols/esb/index.rst +++ b/doc/nrf/protocols/esb/index.rst @@ -61,13 +61,13 @@ ESB requires exclusive access to all fixed and configured resources for the :ref - NRF_TIMER2 - configurable * - DPPI/PPI channels - - 6 channels + - 6 channels (7 channels for nRF53 and nRF54 Series devices) - automatically allocated * - Event generator unit - - NRF_EGU0 events 6 - 7 + - NRF_EGU0 events 6 - 7 (event 8 for nRF54 Series devices) - fixed * - Software interrupt - - 0 + - NRF_SWI0 (unused in nRF54 Series devices) - fixed .. note:: @@ -317,6 +317,12 @@ If the ESB connection is established only between nRF52 and/or nRF53 Series devi When the value of the ``use_fast_ramp_up`` parameter is ``true``, fast ramp-up is enabled, resulting in reduced ramp-up delay of 40 µs. +Furthermore, for the nRF54H20 SoC, you can activate fast switching using the :kconfig:option:`CONFIG_ESB_FAST_SWITCHING` Kconfig option and enable the ramp-up by setting the ``use_fast_ramp_up`` parameter to ``true``. +The fast switching option enables direct switching between RX to TX and TX to RX radio states without entering the disable state. +For the PTX node, this switching occurs after transmitting a packet and before waiting for acknowledgment (TX -> RX). +For the PRX node, this switching occurs after receiving a packet and before transmitting an acknowledgment (RX -> TX). +Enabling this feature can improve the responsiveness and efficiency of the radio communication system by reducing latency. + .. _esb_never_disable_tx: Experimental feature: Never disable transmission stage diff --git a/doc/nrf/protocols/lte/index.rst b/doc/nrf/protocols/lte/index.rst new file mode 100644 index 00000000000..f5bf9361ef7 --- /dev/null +++ b/doc/nrf/protocols/lte/index.rst @@ -0,0 +1,232 @@ +.. _ug_lte: + +LTE +### + +.. contents:: + :local: + :depth: 2 + +Long Term Evolution (LTE) technology enables devices to be connected to a base station without an intermediate device or gateway. +LTE is the fourth-generation (4G) wireless broadband standard built on existing technologies, replacing 3G. +LTE maximizes bandwidth utilization and supports data rates up to 300 Mbps. +The following are main key features of the LTE protocol: + +* Purely packet-based. +* Provides significantly high data rates. +* Improves latency. +* It uses the spectrum more efficiently. +* It supports scalable carrier bandwidths. +* It includes robust security features. +* It is designed to be backward compatible. + +LTE is managed by the 3rd Generation Partnership Project (3GPP). +They develop and maintain the cellular standards, which are structured as releases. + +Nordic Semiconductor offers a wide range of cellular products that support LTE connectivity, particularly focusing on the LTE-M and NB-IoT standards. +For more information on the products, see `Cellular IoT SiPs`_. + +LTE-M and NB-IoT +**************** + +LTE-M is a low-power wide-area network (LPWAN) communication standard, introduced in 3GPP release 13. +It offers higher bandwidth and lower latency compared to other similar technologies. +This makes it suited for applications such as asset tracking, health monitors, alarm panels, environmental monitoring, and smart parking. + +NB-IoT, or Narrowband IoT, is another LPWAN communication standard that was introduced in 3GPP release 13. +It is designed for indoor coverage, low cost, and long battery life. +NB-IoT operates in a small radio frequency band of 200 kHz. +It is ideal for applications like smart metering, environmental monitoring, and smart lighting. + +nRF91 Series devices such as nRF9161 DK, nRF9160 DK, and Thingy:91 support both LTE-M and NB-IoT technologies. + +Comparison between LTE-M and NB-IoT +=================================== + +The following table shows a comparison between LTE-M and NB-IoT in terms of advantages in using any of these standards: + ++------------------+--------------------------------+--------------------------------+ +| | LTE-M | NB-IoT | ++==================+================================+================================+ +| | Higher throughput | Longer range | ++ +--------------------------------+--------------------------------+ +| | Lower latency | Better penetration | ++ +--------------------------------+--------------------------------+ +| Strengths | Better roaming agreements | Power efficient at lower data | +| | | rate | ++ +--------------------------------+--------------------------------+ +| | Power efficient at medium data | | +| | rate | | ++ +--------------------------------+--------------------------------+ +| | Suitable for TCP/TLS secure | | +| | connection | | ++------------------+--------------------------------+--------------------------------+ + +You can find the key feature comparison between LTE-M and NB-IoT in the `nWP044 - Best practices for cellular IoT development`_ documentation. + +Factors to be considered for LTE +******************************** + +Following are some key aspects to ensure LTE support for your SiP using Nordic Semiconductor's devices, such as the nRF91 Series. + +LTE bands +========= + +There are 56 LTE bands from 400 MHz to 6 GHz. +Some bands use :term:`Frequency Division Duplex (FDD)` and some use :term:`Time Division Duplex (TDD)`. +The different bands are licensed by different Mobile Network Operators (MNO) around the world. +Half-duplex operation opens for much simpler multiband support and enables :term:`User equipment (UE)` to operate in a larger region. +For LTE-M and NB-IoT, the only known deployment is FDD. + +nRF91 Series SiPs support up to 18 LTE bands for global operation. +For details of LTE band support in an nRF91 Series SiP for LTE-M and NB-IoT, see `nRF9161 Product Specification`_ or `nRF9160 Product Specification`_, depending on the SiP you are using. + +Physical layer parameters +------------------------- + +The following table provides physical layer parameters for LTE-M and NB-IoT: + ++----------------------------------+----------------------------------+----------------------------------+ +| | LTE-M | NB-IoT | ++==================================+==================================+==================================+ +| Bandwidth | 1.4 MHz | 200 kHz | ++----------------------------------+----------------------------------+----------------------------------+ +| Antenna Techniques | Single antenna | Single antenna | ++----------------------------------+----------------------------------+----------------------------------+ +| OFDM subcarriers | 72 subcarriers | 12 subcarriers | ++----------------------------------+----------------------------------+----------------------------------+ +| Duplexing | Full-duplex or half-duplex, | Half-duplex | +| | but networks use only | | +| | half-duplex FDD | | ++----------------------------------+----------------------------------+----------------------------------+ +| Modulation in :term:`Uplink (UL)`| QPSK or 16QAM in both UL and DL | BPSK or QPSK in UL depending on | +| and :term:`Downlink (DL)` | depending on signal quality | signal quality, | +| | | only QPSK in DL | ++----------------------------------+----------------------------------+----------------------------------+ + +Network support +================ + +A factor governing the selection of the access technology is the MNO support in the areas where you wish to deploy your product. +Most cellular operators support both LTE-M and NB-IoT, but there are geographic locations where only one of these is supported. +See `Mobile IoT deployment map`_ for more information. + +Certifications +============== + +Some MNOs, such as Verizon and Vodafone, have their own certification requirements. +In such cases, it is advised to engage with the MNO certification programs and contact them at the earliest. +This is to receive certification-related requirements and better understand the potential certification costs, processes, and timelines. +But many operators only require GCF (Global Certification Forum) or PTCRB certifications that devices work as per standard, and regulatory certifications. + +For more information about certification related to the nRF91 Series SiP, refer to the following pages: + +* `nRF91 Series certifications`_ +* `Certifying a cellular IoT device`_ + +SIM card support +================ + +SIMs that are used with the nRF91 Series devices must support LTE-M, NB-IoT, or both. +The iBasis SIM is bundled with the nRF9160 DK and Thingy:91, and Onomondo SIM is bundled with the nRF9161 DK. +Check the `iBasis IoT network coverage`_, `Onomondo LTE-M coverage`_, or `Onomondo NB-IoT coverage`_ pages to see the network coverage for different countries, depending on the SIM card you are using. + +Software SIM +------------ + +The nRF91 Series supports software SIM, which allows the usage of software SIM-based solutions to reduce energy consumption associated with physical SIMs. +The following are some of the key advantages of using software SIM: + +* Cost savings and simplified design by excluding the SIM hardware layer. +* Power savings, especially in idle mode using :term:`Extended Discontinuous Reception (eDRX)`. + +The traditional carriers (not MVNOs like iBasis or Onomondo) do not allow their profiles to be provisioned or uploaded into SoftSIMs. +These carriers need to use profiles from SoftSIM providers like Onomondo. +See the software SIM support section of the `Cellular IoT unique features`_ documentation for information on software SIM. + +The software SIM support is available in the |NCS| from the v2.5.0 release. +The `Onomondo SoftSIM integration with the nRF91 Series`_ guide describes the integration of software SIM into |NCS|, and the :ref:`nrf_modem_softsim` guide demonstrates the transfer of SIM data between the modem and the application. + +Power consumption +================= + +Both LTE-M and NB-IoT support :term:`Power Saving Mode (PSM)`, eDRX, and :term:`Release Assistance Indication (RAI)` to minimize power consumption. +For more information on power-saving techniques, refer to the DevAcademy's `Power saving techniques`_ documentation. + +Security +======== + +The nRF91 Series devices include a range of security features, such as Arm TrustZone and Arm CryptoCell for secure application and data handling. +For more information, refer to the :ref:`app_boards_spe_nspe` documentation. + +Security best practices are also implemented to protect data transmitted over the LTE network. +This includes using Transport Layer Security (TLS) for Transmission Control Protocol (TCP) and Datagram Transport Layer Security (DTLS) for User Datagram Protocol (UDP). +For more information, refer to the `Security protocol for cellular IoT`_ documentation. + +Getting started with cellular products +************************************** + +For getting started with the cellular products, you can refer to the :ref:`ug_nrf91` documentation, which guides through the features, getting started steps, and advanced usage of the boards. +For a self-paced, hands-on course, enroll in DevAcademy's `Cellular IoT Fundamentals course`_, which describes the LTE and NB-IoT technologies and the software architecture of a cellular IoT application based on Nordic Semiconductor nRF91 Series devices. + +The :ref:`nrf9160_ug_network_mode` section provides information about switching between LTE-M and NB-IoT. + +Cellular IoT in |NCS| +********************* + +The following sections explain the different applications, libraries, and samples that use the cellular IoT products. + +Modem library +============= + +.. include:: ../../device_guides/working_with_nrf/nrf91/nrf91_features.rst + :start-after: nrf91_modem_lib_start + :end-before: nrf91_modem_lib_end + +Library support +=============== + +The following |NCS| libraries are used for cellular IoT: + +* :ref:`lib_modem` +* :ref:`lib_networking` +* :ref:`liblwm2m_carrier_readme` library +* :ref:`mod_memfault` library + +Applications and samples +======================== + +The following applications use the cellular IoT in |NCS|: + +* :ref:`asset_tracker_v2` +* :ref:`serial_lte_modem` +* :ref:`connectivity_bridge` + +The following samples are used for the cellular IoT development in |NCS|: + +* :ref:`cellular_samples`. +* :ref:`memfault_sample` sample. +* :ref:`networking_samples` - These samples use an nRF91 Series device over LTE or an nRF70 Series device over Wi-Fi® for communication and connection. + +Integrations +============ + +The following integrations are available for cellular IoT in |NCS|: + +* `nRF Asset Tracker project`_. +* :ref:`nRF Cloud ` - `nRF Cloud`_ is `Nordic Semiconductor's IoT cloud platform`_ that allows you to remotely manage and update your IoT devices using :term:`Firmware Over-the-Air (FOTA) `. +* :ref:`Memfault ` - A cloud-based web application with |NCS| compatibility that monitors devices and allows you to debug issues remotely through an LTE or Wi-Fi network. +* :ref:`AVSystem ` - Software solution provider that provides a device management platform. + +Power optimization +================== + +For optimizing the power consumption of your cellular application, you can use the `Online Power Profiler (OPP)`_ tool. +See :ref:`app_power_opt_nRF91` for more information. + +References +********** + +* `nWP044 - Best practices for cellular IoT development`_ whitepaper - Describes the guidelines that you need to consider when you start the development for a low power cellular IoT product. +* `How nRF9160 enables cellular IoT asset tracking`_ webinar. +* `Accelerate cellular product development`_ webinar. diff --git a/doc/nrf/protocols/matter/end_product/attestation.rst b/doc/nrf/protocols/matter/end_product/attestation.rst index 6c7d1991814..442de4a3501 100644 --- a/doc/nrf/protocols/matter/end_product/attestation.rst +++ b/doc/nrf/protocols/matter/end_product/attestation.rst @@ -36,7 +36,7 @@ During the Device Attestation procedure, the commissioner checks the certificate These certificates form a chain in which they mutually rely on each other. All certificates come from Matter certification authorities (CAs). -The primary source of Matter certification authority policies is Connectivity Standards Alliance's Test and Certification Oversight Committee (TCOC), which develops them in accordance with `Connectivity Standards Alliance Certification Policy`_. +The primary source of Matter certification authority policies is Connectivity Standards Alliance's Test and Certification Oversight Committee (TCOC), which develops them in accordance with `Connectivity Standards Alliance Certification Policy`_ (authorized access required). CSA assigns the status of Product Attestation Authority (PAA) to selected organizations, which become root certificate authorities for the Device Attestation procedure. Each PAA owns a key pair, which consists of a private and a public key, and the self-signed PAA certificate. @@ -123,7 +123,7 @@ Generating DAC using own PKI (option 2) +++++++++++++++++++++++++++++++++++++++ The manufacturer can set up its own :ref:`ug_matter_device_attestation_cert_pki` to generate PAI and DAC certificates using its own existing PKI. -The rules for setting own PKI are outlined in the `Matter Certification Policy`_ document (authorized access required). +The rules for setting own PKI are outlined in the `Connectivity Standards Alliance Certification Policy`_ document (authorized access required). Setting up own PKI lets the manufacturer obtain the following certificates: * Own PAA - Provided that the manufacturer has a certification authority with root in the DCL. diff --git a/doc/nrf/protocols/matter/end_product/certification.rst b/doc/nrf/protocols/matter/end_product/certification.rst index 23036884d85..bae12cb1aae 100644 --- a/doc/nrf/protocols/matter/end_product/certification.rst +++ b/doc/nrf/protocols/matter/end_product/certification.rst @@ -278,7 +278,7 @@ Nordic Semiconductor provides the following certification identifiers: * Bluetooth Qualified Design IDs (Bluetooth QDIDs) - Obtained in accordance with `Bluetooth SIG's Qualification Process`_. * Thread Certification IDs (Thread CIDs) - Obtained in accordance with `Thread Group's certification information`_. -You can visit the following pages on Nordic Semiconductor Infocenter to check the Bluetooth QDIDs and Thread CIDs valid for SoCs that support Matter applications: +You can visit the following pages to check the Bluetooth QDIDs and Thread CIDs valid for SoCs that support Matter applications: * `nRF5340 DK Compatibility Matrix`_ * `nRF52840 DK Compatibility Matrix`_ @@ -342,7 +342,7 @@ The |NCS| includes several :ref:`matter_samples` that are example implementation The samples are maintained to fulfill Matter certification requirements as closely as possible, but they do not have official Matter compliance certificates. You can use them as a reference for creating your own application, but this does not guarantee that your application will pass the Matter certification. -The Matter certification program currently does not provide any form of platform certification, so the product maker is solely reponsible for ensuring that the application used fulfills all Matter certification requirements. +Currently, the Matter certification program does not provide any form of platform certification, so the product maker is solely responsible for ensuring that the application used fulfills all Matter certification requirements. Before you start the application process for the Matter certification, make sure that the application configuration generated using :file:`.zap` file is compatible with the PICS generated for the certification purpose. You can find the information about the specification and the valid PICS for specific Matter stack version that should be used for your product on the `CSA Matter Resource Kit`_ page, in the `Specification` section. Especially, make sure that: diff --git a/doc/nrf/protocols/matter/end_product/configuring_cd.rst b/doc/nrf/protocols/matter/end_product/configuring_cd.rst index b23eb2ba7ee..99d7684ca6d 100644 --- a/doc/nrf/protocols/matter/end_product/configuring_cd.rst +++ b/doc/nrf/protocols/matter/end_product/configuring_cd.rst @@ -25,7 +25,7 @@ You can locate the array of bytes related to CD by running the search with the f .. code-block:: console - cat CD.der | xxd -I + cat CD.der | xxd -i Storing Certification Declaration in Zephyr =========================================== diff --git a/doc/nrf/protocols/matter/end_product/index.rst b/doc/nrf/protocols/matter/end_product/index.rst index bd8eb0b67a9..61c67eabeb6 100644 --- a/doc/nrf/protocols/matter/end_product/index.rst +++ b/doc/nrf/protocols/matter/end_product/index.rst @@ -19,7 +19,7 @@ Watch the following video for an overview of the Matter end product development The pages that follow deal with the preparation of the device for market launch, starting with :ref:`ug_matter_device_prerequisites` and the reference to the :ref:`ug_matter_device_factory_provisioning` guide. -Finally, we discuss topics related to Matter certification (:ref:`ug_matter_device_attestation`, :ref:`ug_matter_device_dcl`, :ref:`ug_matter_device_certification`, :ref:`ug_matter_ecosystems_certification`, and :ref:`ug_matter_device_configuring_cd`) and :ref:`ug_matter_device_bootloader`. +Finally, we discuss topics related to Matter certification (:ref:`ug_matter_device_attestation`, :ref:`ug_matter_device_dcl`, :ref:`ug_matter_device_certification`, :ref:`ug_matter_ecosystems_certification`, :ref:`ug_matter_device_configuring_cd`, and :ref:`ug_matter_test_event_triggers`) and :ref:`ug_matter_device_bootloader`. .. toctree:: :maxdepth: 1 @@ -34,4 +34,6 @@ Finally, we discuss topics related to Matter certification (:ref:`ug_matter_devi bootloader security configuring_cd + versioning last_fabric_removal_delegate + test_event_triggers diff --git a/doc/nrf/protocols/matter/end_product/security.rst b/doc/nrf/protocols/matter/end_product/security.rst index 454f2abb7ca..84988a7d831 100644 --- a/doc/nrf/protocols/matter/end_product/security.rst +++ b/doc/nrf/protocols/matter/end_product/security.rst @@ -1,16 +1,141 @@ .. _ug_matter_device_security: -Securing production devices -########################### +Security +######## .. contents:: :local: - :depth: 2 + :depth: 3 + +Nordic Matter samples leverage security features supported in the |NCS| that can be divided into three major categories: + +* Cryptography +* Trusted storage +* Securing production devices + +In the following sections you will learn more details about each listed category. + +Cryptography +************ + +Depending on the networking backend, the |NCS| Matter samples currently use the following APIs to implement cryptographic operations: + +* PSA Cryptography API for Thread networking. +* Mbed TLS for Wi-Fi networking. + Support for PSA Cryptography API for the Wi-Fi backend is planned for a future release. + +Both APIs are integrated in the :ref:`nrf_security` library. +This library offers various configuration possibilities and backends that can be employed to implement :ref:`cryptographic operations `. +You can find an overview of the cryptography layer configuration supported for each |NCS| Matter-enabled platform in the :ref:`matter_platforms_security_support` section. + +Trusted storage +*************** + +:ref:`trusted_storage_in_ncs` is a security mechanism designed to securely store and manage sensitive data, such as cryptographic keys, device credentials, and configuration data. +The mechanism is essential for IoT devices, as it allows the implementation of secure communication between devices. + +The Trusted Storage can utilize one of the following backends to implement PSA Certified Secure Storage API: + +* TF-M Platform Root of Trust (PRoT). + This can only be utilized if the `ARM TrustZone`_ technology and hardware-accelerated firmware isolation are supported by the platform in use. +* The :ref:`trusted_storage_readme` |NCS| software library. + +Currently all :ref:`matter_samples` in the |NCS| use the trusted storage library as a Trusted Storage backend for all supported platforms. + +The trusted storage library provides confidentiality, integrity, and authenticity for the assets it operates on. +It handles sensitive data in two contexts: + +* Volatile - Before data is forwarded to the non-volatile storage and after it is retrieved from the non-volatile storage. +* Non-volatile - When data is written to the non-volatile memory in encrypted form. + +In the case of the volatile context, the trusted storage library leverages the Authenticated Encryption with Associated Data (AEAD) encryption backend (:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD`). +It is used to encrypt and decrypt the assets that are being securely stored in the non-volatile memory. +AEAD can be configured with the set of Kconfig options described in the library's :ref:`trusted_storage_configuration` section. + +An important setting, that depends on the hardware platform in use, is the way of generating the AEAD keys. +The recommended and the most secure option is to use :ref:`lib_hw_unique_key` (HUK) library. +HUK support is automatically enabled with the :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK` Kconfig option for compatible configurations. + +The HUK library is supported for both the nRF52840 and nRF5340 platforms, but for :ref:`matter_samples` in the |NCS|, it is only enabled for the nRF5340 platform: + +* For the nRF5340 platform, the HUK is generated at first boot and stored in the Key Management Unit (KMU). + No changes to the existing partition layout are needed for products in the field. +* For the nRF52840 and nRF54L15 platforms, AEAD keys are derived with a SHA-256 hash (:kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_HASH_UID`). + This approach is less secure than using the library for key derivation as it will only provide integrity of sensitive material. + It is also possible to implement a custom AEAD keys generation method when the :kconfig:option:`CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_CUSTOM` Kconfig option is selected. + + Using the HUK library with nRF52840 SoC is possible, but it requires employing the :ref:`bootloader` that would generate the AEAD key at first boot and store it in the dedicated HUK partition that can be accessed only by the CryptoCell peripheral. + Note that adding another partition in the FLASH layout implies breaking the firmware backward compatibility with already deployed devices. + + .. note:: + Using the HUK library with the nRF54L15 SoC is not possible yet. + This means that you need to use AEAD keys derived with a SHA-256 hash. + +You can find an overview of the Trusted Storage layer configuration supported for each |NCS| Matter-enabled platform in the :ref:`matter_platforms_security_support` section. + +.. _matter_platforms_security_support: + +Matter platforms security support +********************************* + +The following table summarizes the current security configuration and features supported for Matter-enabled hardware platforms in the |NCS|. +This is a reference configuration that can be modified in the production firmware by using proper Kconfig settings or implementing custom cryptographic backends. + +.. list-table:: Matter platforms security support + :widths: auto + :header-rows: 1 + + * - Platform + - Networking backend + - Cryptography API + - Cryptography backend + - ARM TrustZone support + - Trusted Storage backend + - Trusted Storage AEAD key + * - nRF52840 SoC + - Thread + - PSA + - Oberon + CryptoCell [1]_ + - No + - Trusted Storage library + - SHA-256 hash + * - nRF5340 SoC + - Thread + - PSA + - Oberon + CryptoCell [1]_ + - Yes + - Trusted Storage library + - Hardware Unique Key (HUK) + * - nRF5340 SoC + nRF7002 companion IC + - Wi-Fi + - Mbed TLS + - Oberon + CryptoCell [1]_ + - Yes + - --- + - --- + * - nRF54L15 SoC + - Thread + - PSA + - CRACEN + Oberon [2]_ + - Yes + - Trusted Storage backend + - SHA-256 hash + +.. [1] The CryptoCell backend is used in parallel with the Oberon backend. + It is only used to implement Random Nuber Generation (RNG), and the AED keys derivation driver (only for Thread networking). + For all other cryptographic operations, the Oberon backend is used. + +.. [2] When the CRACEN driver is used in parallel with the Oberon driver, you need to disable specific CRACEN cryptographic operations to use the Oberon ones. + This is because the CRACEN driver has priority when both are enabled. + See the :ref:`nrf_security_drivers` documentation for more information. + +Securing production devices +*************************** When finalizing work on a Matter device, make sure to adopt the following recommendations before sending the device to production. Enable AP-Protect -***************** +================= Make sure to enable the AP-Protect feature for the production devices to disable the debug functionality. @@ -21,7 +146,7 @@ Make sure to enable the AP-Protect feature for the production devices to disable See :ref:`app_approtect` for more information. Disable debug serial port -************************* +========================= Make sure to disable the debug serial port, for example UART, so that logs and shell commands are not accessible for production devices. See the :file:`prj_release.conf` files in :ref:`Matter samples ` for an example of how to disable debug functionalities. diff --git a/doc/nrf/protocols/matter/end_product/test_event_triggers.rst b/doc/nrf/protocols/matter/end_product/test_event_triggers.rst new file mode 100644 index 00000000000..c5f5386b2d3 --- /dev/null +++ b/doc/nrf/protocols/matter/end_product/test_event_triggers.rst @@ -0,0 +1,283 @@ +.. _ug_matter_test_event_triggers: + +Matter test event triggers +########################## + +.. contents:: + :local: + :depth: 2 + +Matter test event triggers are a set of software commands designed to initiate specific test scenarios. +You can activate these commands using the Matter Controller, which serves as the interface for executing them. +To activate a command, you need to enter the pre-defined activation codes that correspond to the desired test event. +All test event triggers are based on the ``generaldiagnostics`` Matter cluster, and utilize the ``test-event-trigger`` command to function. +This mechanism can be used during the Matter certification process to simulate common and specific device scenarios, and during software verification events to validate the correct operation of Matter-compliant devices. +To learn how to use the test event triggers functionality during the Matter certification process, see the :ref:`matter_test_event_triggers_matter_certification` section. + +You can utilize the test event triggers predefined in the :ref:`matter_test_event_triggers_default_test_event_triggers` section to streamline your testing process. +If the predefined options do not meet your requirements, you can also define your own event triggers. +To learn how to create custom event triggers, refer to the :ref:`matter_test_event_triggers_custom_triggers` section of the documentation. + +Requirements +************ + +The :ref:`CHIP Tool application ` is required to send ``test-event-trigger`` commands to the general diagnostics cluster. +Ensure that it is installed before initiating Matter testing events. + +Your device needs to includes the general diagnostics cluster within its Matter data model database to perform Matter testing events. +For guidance on configuring the general diagnostics cluster on your device, refer to the instructions provided on the :ref:`ug_matter_gs_adding_cluster` page. + +Activation of test event codes requires the provisioning of an enable key. +To ensure secure operation, the enable key must be specific for each device. +You can find instructions on how to establish the enable key for your device in the :ref:`matter_test_event_triggers_setting_enable_key` section. + +.. _matter_test_event_triggers_default_test_event_triggers: + +Default test event triggers +*************************** + +You can use the pre-defined common test event triggers in your application. +To disable them, set the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_TEST_EVENT_TRIGGERS_REGISTER_DEFAULTS` Kconfig option to ``n``. + +The following table lists the available triggers and their activation codes: + +.. list-table:: Default test event triggers + :widths: auto + :header-rows: 1 + + * - Name + - Requirements + - Description + - Activation code [range] + - Value description + * - Factory reset + - None + - Perform a factory reset of the device with a delay. + - `0xF000000000000000` - `0xF00000000000FFFF` + - The range of `0x0000` - `0xFFFF` represents the delay in ms to wait until the factory reset occurs. + The maximum time delay is UINT32_MAX ms. + The value is provided in HEX format. + * - Reboot + - None + - Reboot the device. + - `0xF000000000000000` - `0xF00000000000FFFF` + - The range of `0x0000` - `0xFFFF` represents the delay in ms to wait until the reboot occurs. + The maximum time delay is UINT32_MAX ms. + The value is provided in HEX format. + * - OTA query + - :kconfig:option:`CONFIG_CHIP_OTA_REQUESTOR` = ``y`` + - Trigger an OTA firmware update. + - `0x002a000000000100` - `0x01000000000001FF` + - The range of `0x00` - `0xFF` is the fabric index value. + The maximum fabric index value depends on the current device's settings. + * - Door lock jammed + - :kconfig:option:`CONFIG_CHIP_DEVICE_PRODUCT_ID` = ``32774`` + - Simulate the jammed lock state. + - `0x3277400000000000` + - This activation code does not contain any value. + +.. _matter_test_event_triggers_setting_enable_key: + +Setting the enable key +********************** + +The enable key can be provided either by utilizing the factory data, or directly in the application code. + +Using factory data +================== + +You can not set the enable key to a specific value using factory data unless the :kconfig:option:`CONFIG_CHIP_FACTORY_DATA` Kconfig option is set to ``y``. +If it is not set, the default value ``00112233445566778899AABBCCDDEEFF`` will be used. +For secure operation, you need to ensure that the enable key is unique for all of your devices. + +To specify the enable key through the build system, enable the :kconfig:option:`CONFIG_CHIP_FACTORY_DATA_BUILD` Kconfig option by setting it to ``y``. +Then, set the :kconfig:option:`CONFIG_CHIP_DEVICE_ENABLE_KEY` Kconfig option to a 32-byte hexadecimal string value. + +If :kconfig:option:`CONFIG_CHIP_FACTORY_DATA_BUILD` is set to ``n``, you can follow the :doc:`matter:nrfconnect_factory_data_configuration` guide in the Matter documentation to generate the factory data set with the specific enable key value. + +If you do not use the |NCS| Matter common module, you need to read the enable key value manually from the factory data set and provide it to the ``TestEventTrigger`` class. + +For example: + +.. code-block:: c++ + + /* Prepare the factory data provider */ + static chip::DeviceLayer::FactoryDataProvider sFactoryDataProvider; + sFactoryDataProvider.Init(); + + /* Prepare the buffer for enable key data */ + uint8_t enableKeyData[chip::TestEventTriggerDelegate::kEnableKeyLength] = {}; + MutableByteSpan enableKey(enableKeyData); + + /* Load the enable key value from the factory data */ + sFactoryDataProvider.GetEnableKey(enableKey); + + /* Call SetEnableKey method to load the read value to the TestEventTrigger class. */ + Nrf::Matter::TestEventTrigger::Instance().SetEnableKey(enableKey); + +Directly in the code +==================== + +Use the SetEnableKey method of the ``TestEventTrigger`` class to set up the enable key. + +For example: + +.. code-block:: c++ + + /* Prepare Buffer for Test Event Trigger data which contains your "enable key" */ + uint8_t enableKeyData[chip::TestEventTriggerDelegate::kEnableKeyLength] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff + }; + + /* Call SetEnableKey method to load the prepared value to the TestEventTrigger class. */ + Nrf::Matter::TestEventTrigger::Instance().SetEnableKey(ByteSpan {enableKeyData}); + +.. _matter_test_event_triggers_matter_certification: + +Using in Matter certification +***************************** + +When you provide the enable key using factory data, you can utilize the event trigger feature during the Matter certification process. +This is because, when done this way, you can turn off the event trigger functionality by disabling access to the ``generaldiagnostics`` cluster without altering the code that has already been certified. + +Once the certification process is complete, you must deactivate the test event trigger functionality by generating new factory data with a modified enable key value. +This is done by setting the :kconfig:option:`CONFIG_CHIP_DEVICE_ENABLE_KEY` Kconfig option to a value consisting solely of zeros. + +For instance, to generate factory data with disabled event trigger functionality, set the :kconfig:option:`CONFIG_CHIP_DEVICE_ENABLE_KEY` Kconfig option to the value ``0x00000000000000000000000000000000``. +After generating it, flash the :file:`factory_data.hex` file onto the device. + +.. _matter_test_event_triggers_custom_triggers: + +Custom test event triggers +************************** + +You can define and register custom test event triggers to initiate specific actions on your device. + +An activation code is 64 bits in length, and consist of two components: the event trigger ID and the event trigger value. + +* The event trigger ID is 32 bits long and uniquely identifies the trigger. + It is supplied as the first 32 bits of the activation code. +* The event trigger value is specific to a given trigger. + It is supplied as the last 32 bits of the activation code. + +This means that the activation code has the pattern ``0xIIIIIIIIVVVVVVVV``, where ``I`` represents the ID part and ``V`` represents the value part. + +For example the ``0x1000000000001234`` activation code stands for a trigger ID equal to ``0x1000000000000000`` and a specific value of ``0x1234``. + +A new event trigger consists of two fields: ``Mask``, and ``Callback``. + +* The ``Mask`` field is 32 bits long and specifies a mask for the trigger's value. +* The ``Callback`` field is a callback function that will be invoked when the device receives a corresponding activation code. + +The maximum number of event triggers that can be registered is configurable. +To adjust this limit, set the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_TEST_EVENT_TRIGGERS_MAX` Kconfig option to the desired value. + +To register a new test event trigger, follow these steps: + +1. Create a function that will be executed when the device receives a valid enable key and activation code. + + This function must return a ``CHIP_ERROR`` code and accept a ``Nrf::Matter::TestEventTrigger::TriggerValue`` as its argument. + You can utilize the provided argument within this function as needed. + + Use ``CHIP_ERROR`` codes to communicate appropriate responses to the Matter Controller. + For instance, you might return ``CHIP_ERROR_INVALID_ARGUMENT`` to indicate that the user has provided an incorrect value argument. + + .. note:: + + The callback method is not thread-safe. + Ensure that all operations within it are executed in a thread-safe manner. + To perform operations within the Matter stack context, use the ``chip::DeviceLayer::SystemLayer().ScheduleLambda`` method. + For operations in the application context, use the ``Nrf::PostTask`` function. + + Here is an example of how to create a callback function: + + .. code-block:: c++ + + CHIP_ERROR MyFunctionCallback(Nrf::Matter::TestEventTrigger::TriggerValue value) + { + /* Define the required behavior of the device here. */ + + return CHIP_NO_ERROR; + } + +#. Register the new event trigger. + + Use the following example as a guide to register a new event: + + .. code-block:: c++ + + /* Create a new event */ + Nrf::Matter::TestEventTrigger::EventTrigger myEventTrigger; + + /* Assign all fields */ + uint64_t myTriggerID = /* Set the trigger ID */ + myEventTrigger.Mask = /* Fill the value mask filed */; + myEventTrigger.Callback = MyFunctionCallback; + + /* Register the new event */ + CHIP_ERROR err = Nrf::Matter::TestEventTrigger::Instance().RegisterTestEventTrigger(myTriggerID, myEventTrigger); + + /* Remember to check the CHIP_ERROR return code */ + + If the returning `CHIP_ERROR` code is equal to `CHIP_ERROR_NO_MEMORY`, you need to increase the :kconfig:option:`NCS_SAMPLE_MATTER_TEST_EVENT_TRIGGERS_MAX` kconfig option to the higher value. + + Here's an example to handle the ``0xF000F00000001234`` activation code, where 1234 is the event trigger value field: + + .. code-block:: c++ + + Nrf::Matter::TestEventTrigger::EventTrigger myEventTrigger; + uint64_t myTriggerID = 0xF000F0000000; + myEventTrigger.Mask = 0xFFFF; + myEventTrigger.Callback = MyFunctionCallback; + + CHIP_ERROR err = Nrf::Matter::TestEventTrigger::Instance().RegisterTestEventTrigger(myTriggerID, myEventTrigger); + +Register an existing test event trigger handler +*********************************************** + +The Matter SDK has some test event trigger handlers implemented. +All of them inherit the `TestEventTriggerHandler` class, and are implemented in various places in the Matter SDK. + +The events declared in existing test event triggers can have a different semantic than described in the :ref:`matter_test_event_triggers_custom_triggers` section. + +Use the following example as a guide to register an existing event trigger handler: + +.. code-block:: c++ + + /* Create the Trigger Handler object */ + static TestEventTriggerHandler existingTriggerHandler; + CHIP_ERROR err = Nrf::Matter::TestEventTrigger::Instance().RegisterTestEventTriggerHandler(&existingTriggerHandler); + + /* Remember to check the CHIP_ERROR return code */ + +If the returning ``CHIP_ERROR`` code is equal to ``CHIP_ERROR_NO_MEMORY``, you need to increase the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_TEST_EVENT_TRIGGERS_MAX_TRIGGERS_DELEGATES` kconfig option to the higher value. + +For example, you can register and use the ``OTATestEventTriggerHandler`` handler and trigger pre-defined Matter OTA DFU behaviors using the following code: + +.. code-block:: c++ + + /* Create the Trigger Handler object */ + static chip::OTATestEventTriggerHandler otaTestEventTrigger; + ReturnErrorOnFailure(Nrf::Matter::TestEventTrigger::Instance().RegisterTestEventTriggerHandler(&otaTestEventTrigger)); + +Usage +***** + +The Matter test event triggers feature is enabled by default for all Matter samples. +To disable it, set the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_TEST_EVENT_TRIGGERS` kconfig option to ``n``. + +To trigger a specific event on the device, run the following command: + +.. code-block:: console + + ./chip-tool generaldiagnostics test-event-trigger hex: 0 + +Replace the ``enable key`` value with your device's enable key, and the ``activation code`` and ``node id`` values with the values for the event you want to trigger. + +The following is an example of the Reboot activation code with a 5 ms delay for Matter Template device which has a ``node id`` set to ``1``, using the default enable key: + +.. code-block:: console + + ./chip-tool generaldiagnostics test-event-trigger hex:00112233445566778899AABBCCDDEEFF 0xF000000100000005 1 0 diff --git a/doc/nrf/protocols/matter/end_product/versioning.rst b/doc/nrf/protocols/matter/end_product/versioning.rst new file mode 100644 index 00000000000..3f572e3b7e4 --- /dev/null +++ b/doc/nrf/protocols/matter/end_product/versioning.rst @@ -0,0 +1,100 @@ +.. _ug_versioning_in_matter: + +Maintaining firmware version +############################ + +.. contents:: + :local: + :depth: 2 + +To effectively deploy a Matter product, it is essential to implement application version management. +This versioning is crucial for managing firmware upgrades on devices. +It is also displayed within ecosystem applications, as provided by the Basic Information cluster. + +There are two primary approaches for maintaining versioning: + +* Utilizing a :file:`VERSION` file as detailed on the :ref:`app-version-details` page of the Zephyr Project documentation. + This method involves defining the version information in a specific file format. + +* Implementing dedicated Kconfig configurations. + This approach uses Kconfig system configurations to set and manage the versioning details. + +Choose the approach that best aligns with your project requirements and infrastructure. + +.. note:: + These approaches should not be used simultaneously. + +Using :file:`VERSION` file +************************** + +To implement versioning based on a :file:`VERSION` file, you must create a file named :file:`VERSION` within the application directory and ensure it contains the appropriate content: + +.. code-block:: console + + VERSION_MAJOR = + VERSION_MINOR = + PATCHLEVEL = + VERSION_TWEAK = + +.. note:: + You must assign a value to at least one of the variables. + If not, the :file:`VERSION` file will cause error. + +For example: + +.. code-block:: console + + VERSION_MAJOR = 2 + VERSION_MINOR = 5 + PATCHLEVEL = 99 + VERSION_TWEAK = 0 + +A :file:`VERSION` file is responsible for assigning values in the following format for: + +* MCUboot version: ``MAJOR . MINOR . PATCHLEVEL + TWEAK``. + The above example would be formatted as ``2 . 5 . 99 + 0``. +* Matter OTA: in the 32-bit integer where each variable is 8 bits long. + The above example would be formatted as ``0x02056300``. + +Using Kconfig options +********************* + +Depending on how you transfer the updated images to the device, you need to use different Kconfig options. + +.. _ug_matter_dfu_ota: + +Device Firmware Upgrade over Matter versioning +============================================== + +When using DFU over Matter, you must edit the :file:`prj.conf` file in the application directory. +Add the following Kconfig options to change the version: + +* :kconfig:option:`CONFIG_CHIP_DEVICE_SOFTWARE_VERSION` to set to the version number. +* :kconfig:option:`CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING` to set the version string. + +Additionally, since Nordic chips use MCUboot Image Tool, you need to also edit the :kconfig:option:`CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` Kconfig option, with a value in the following format: ``"MAJOR . MINOR . PATCHLEVEL + TWEAK"``. + +For example: + +.. code-block:: console + + CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=33907456 + CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING="2.5.99+0" + CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="2.5.99+0" + +Where ``33907456`` is 0x02056300, the hexadecimal versioning of 2.5.99+0. + +.. _ug_matter_dfu_smp: + +Device Firmware Upgrade over Bluetooth LE versioning +==================================================== + +For DFU over Bluetooth LE, you need to edit the :kconfig:option:`CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` Kconfig option in the :file:`prj.conf` file in the application directory. +Set its value in the following format: ``"MAJOR . MINOR . PATCHLEVEL + TWEAK"``. + +.. _ug_matter_dfu_performing: + +Performing Device Firmware Upgrade +********************************** + +After properly configuring the application version, you can perform device firmware upgrade as explained in :doc:`matter:nrfconnect_examples_software_update`. diff --git a/doc/nrf/protocols/matter/getting_started/adding_clusters.rst b/doc/nrf/protocols/matter/getting_started/adding_clusters.rst index c82241f2dd5..c19a04d6b89 100644 --- a/doc/nrf/protocols/matter/getting_started/adding_clusters.rst +++ b/doc/nrf/protocols/matter/getting_started/adding_clusters.rst @@ -181,53 +181,26 @@ This is needed to properly model the sensor's behavior. The :file:`src/app_task.cpp` file contains the main loop of the application. Complete the steps in the following subsections to modify the main loop. -Edit the event queue -==================== +Add new tasks +============= -The main application loop is based on an ``AppEventQueue``, on which events are posted by ZCL callbacks and by other application components, such as Zephyr timers. -In each iteration, an event is dequeued and a corresponding event handler is called. +The main application uses a task queue managed by the ``task_executor`` common module, on which tasks are posted by ZCL callbacks and by other application components, such as Zephyr timers. +In each iteration, a task is dequeued and a corresponding task handler is called. -Add new events --------------- +To model the behavior of the sensor, you should add new tasks in the following subsections: -After you copied the template sample application, the following events are used in the application (:file:`src/app_event.h`): - -* :c:enum:`Button` - For general operation of **Button 1**. -* :c:enum:`ButtonPushed` - For pressing **Button 1**. -* :c:enum:`ButtonReleased` - For releasing **Button 1**. -* :c:enum:`Timer` - For factory reset timeout. -* :c:enum:`UpdateLedState` - For updating of the **LED 1** state. - -To model the behavior of the sensor, add the following new :c:enum:`AppEventType` events: - -* :c:enum:`SensorActivate` - For sensor activation. -* :c:enum:`SensorDeactivate` - For sensor deactivation. -* :c:enum:`SensorMeasure` - For sensor measurement update. - -For example, the edited :c:enum:`AppEventType` can look as follows: - -.. code-block:: C++ - - enum class AppEventType { - None = 0, - Button, - ButtonPushed, - ButtonReleased, - Timer, - UpdateLedState, - SensorActivate, - SensorDeactivate, - SensorMeasure - }; +* ``Sensor Activate`` - For sensor activation. +* ``Sensor Deactivate`` - For sensor deactivation. +* ``Sensor Measure`` - For sensor measurement update. Add sensor timer ---------------- You need to make sure that the sensor is making measurements at the required time points. -For this purpose, use a Zephyr timer to periodically post :c:enum:`SensorMeasure` events. +For this purpose, use a Zephyr timer to periodically post ``Sensor Measure`` tasks. In the template sample, such a timer is being used to count down 6 seconds when **Button 1** is being pressed to initiate the factory reset. -To add a new timer for the measurement event, edit the :file:`src/app_task.cpp` file as follows: +To add a new timer for the measurement task, edit the :file:`src/app_task.cpp` file as follows: .. code-block:: C++ @@ -235,10 +208,7 @@ To add a new timer for the measurement event, edit the :file:`src/app_task.cpp` void SensorTimerHandler(k_timer *timer) { - AppEvent event; - event.Type = AppEventType::SensorMeasure; - event.Handler = AppTask::SensorMeasureHandler; - AppTask::Instance().PostEvent(event); + Nrf::PostTask([] { AppTask::SensorMeasureHandler(); }); } void StartSensorTimer(uint32_t aTimeoutMs) @@ -259,35 +229,35 @@ To add a new timer for the measurement event, edit the :file:`src/app_task.cpp` k_timer_init(&sSensorTimer, &SensorTimerHandler, nullptr); k_timer_user_data_set(&sSensorTimer, this); - return CHIP_NO_ERROR; + return Nrf::Matter::StartServer(); } The timer must be initialized in the ``Init()`` method of the ``AppTask`` class. -If :c:func:`StartSensorTimer()` is called, the :c:struct:`SensorMeasure` event is added to the event queue every *aTimeoutMs* milliseconds, until :c:func:`StopSensorTimer()` is called. +If :c:func:`StartSensorTimer()` is called, the ``Sensor Measure`` task is added to the tasks queue every *aTimeoutMs* milliseconds, until :c:func:`StopSensorTimer()` is called. -Implement event handlers ------------------------- +Implement task handlers +----------------------- -When an event is dequeued, the application calls the event handler in the :c:func:`DispatchEvent()` function. -Because you have added new events, you must implement the corresponding handlers. +When a task is dequeued, the ``task_executor`` module calls the task handler passed to the :c:func:`PostTask()` function. +Because you need to handle new tasks, you must implement the corresponding handlers. -To add new event handlers, complete the following steps: +To add new task handlers, complete the following steps: 1. Edit the :file:`src/app_task.cpp` file as follows: .. code-block:: C++ - void AppTask::SensorActivateHandler(const AppEvent &) + void AppTask::SensorActivateHandler() { StartSensorTimer(500); } - void AppTask::SensorDeactivateHandler(const AppEvent &) + void AppTask::SensorDeactivateHandler() { StopSensorTimer(); } - void AppTask::SensorMeasureHandler(const AppEvent &) + void AppTask::SensorMeasureHandler() { chip::app::Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Set( /* endpoint ID */ 1, /* temperature in 0.01*C */ int16_t(rand() % 5000)); @@ -317,9 +287,9 @@ To import helper functions for accessing cluster attributes, make sure to includ Create a callback for sensor activation and deactivation ******************************************************** -Handlers for the :c:struct:`SensorActivate` and :c:struct:`SensorDeactivate` events are now ready, but the events are not posted to the event queue. +Handlers for the ``Sensor Activate`` and ``Sensor Deactivate`` tasks are now ready, but the tasks are not posted to the task queue. The sensor is supposed to be turned on and off remotely by changing the ``OnOff`` attribute of the On/off cluster, for example using the Matter controller. -This means that we need to implement a callback function to post one of these events every time the ``OnOff`` attribute changes. +This means that we need to implement a callback function to post one of these tasks every time the ``OnOff`` attribute changes. To implement the callback function, complete the following steps: @@ -335,6 +305,7 @@ For example, the implementation can look as follows: .. code-block:: C++ #include "app_task.h" + #include "app/task_executor.h" #include #include @@ -346,23 +317,18 @@ For example, the implementation can look as follows: void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, uint8_t * value) { - if (attributePath.mClusterId != OnOff::Id || attributePath.mAttributeId != OnOff::Attributes::OnOff::Id) + if (attributePath.mClusterId != OnOff::Id || attributePath.mAttributeId != OnOff::Attributes::OnOff::Id) return; - AppEvent event; - if (*value) { - event.Type = AppEventType::SensorActivate; - event.Handler = AppTask::SensorActivateHandler; - } - else { - event.Type = AppEventType::SensorDeactivate; - event.Handler = AppTask::SensorDeactivateHandler; - } - AppTask::Instance().PostEvent(event); + if (*value) { + Nrf::PostTask([] { AppTask::SensorActivateHandler(); }); + } else { + Nrf::PostTask([] { AppTask::SensorDeactivateHandler(); }); + } } In this implementation, the ``if`` part filters out events other than those that belong to the On/Off cluster. -Then, the callback posts the event for the sensor, namely ``SensorActivate`` if the current value of the attribute is not zero. +Then, the callback posts the task for the sensor, namely ``Sensor Activate`` if the current value of the attribute is not zero. .. _ug_matter_creating_accessory_add_source: @@ -385,7 +351,7 @@ To check if the sensor device is working, complete the following steps: .. include:: ../../../../../samples/matter/template/README.rst :start-after: matter_template_sample_testing_start - :end-before: #. Press **Button 1** + :end-before: #. Keep the **Button 1** #. Activate the sensor by running the following command on the On/off cluster with the correct *node_ID* assigned during commissioning: diff --git a/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst b/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst index 0bbae5710c1..df44f38d1d4 100644 --- a/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst +++ b/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst @@ -64,6 +64,28 @@ This option lets you use the Matter shell commands with :ref:`matter_samples`. See :doc:`matter:nrfconnect_examples_cli` in the Matter documentation for the list of available Matter shell commands. +.. _ug_matter_configuring_settings_shell: + +Matter Settings shell commands +------------------------------ + +You can enable the Matter Settings shell commands to monitor the current usage of the Zephyr Settings NVS. +These commands are useful for verifying that the ``settings`` partition has the proper size and meets the application requirements. + +To enable the Matter Settings shell module, set the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_SETTINGS_SHELL` Kconfig option to ``y``. + +You can use the following shell commands: + +* ``matter_settings peak`` - Read the maximum settings usage peak. +* ``matter_settings reset`` - Reset the peak value. +* ``matter_settings get_size `` - Get the size of the specific entry. +* ``matter_settings current`` - Get the size of the current settings usage. +* ``matter_settings free`` - Get the size of the current free settings space. + +.. note:: + + The Matter Settings shell module is available only for the NVS Zephyr Settings backend. + .. _ug_matter_configuring_device_identification: Matter device identification @@ -100,7 +122,7 @@ To enable the FFS support, set the following configuration options to meet the A * :kconfig:option:`CONFIG_CHIP_DEVICE_TYPE` to the appropriate value, depending on the device used. The value must be compliant with the Matter Device Type Identifier. -Every Matter device must use an unique device identifier for rotating device identifier calculation purpose. +Every Matter device must use a unique device identifier for rotating device identifier calculation purpose. By default, the identifier is set to a random value and stored in the factory data partition. You can choose your own unique identifier value instead by setting the :kconfig:option:`CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID` Kconfig option to ``n`` and using the :kconfig:option:`CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID` Kconfig option. When using your own identifier, the value can be stored in either firmware or factory data. diff --git a/doc/nrf/protocols/matter/getting_started/hw_requirements.rst b/doc/nrf/protocols/matter/getting_started/hw_requirements.rst index f517c7c1716..7643c348391 100644 --- a/doc/nrf/protocols/matter/getting_started/hw_requirements.rst +++ b/doc/nrf/protocols/matter/getting_started/hw_requirements.rst @@ -19,6 +19,7 @@ Currently the following SoCs from Nordic Semiconductor are supported for use wit * :ref:`nRF5340 ` (Matter over Thread and Matter over Wi-Fi through the ``nrf7002ek`` shield) * :ref:`nRF5340 + nRF7002 ` (Matter over Thread and Matter over Wi-Fi) * :ref:`nRF52840 ` (Matter over Thread) +* :ref:`nRF54L15 ` (Matter over Thread) Front-End Modules ================= @@ -56,65 +57,77 @@ Values are provided in kilobytes (KB). The following table lists memory requirements for samples running on the :ref:`nRF52840 DK ` (:ref:`nrf52840dk_nrf52840 `). - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | - +==================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 28 | 839 | 4 | 32 | 903 | 175 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 28 | 735 | 4 | 32 | 799 | 169 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 28 | 787 | 4 | 32 | 851 | 166 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 28 | 689 | 4 | 32 | 753 | 159 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 28 | 811 | 4 | 32 | 875 | 166 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 28 | 691 | 4 | 32 | 755 | 160 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 28 | 751 | 4 | 32 | 815 | 164 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 28 | 659 | 4 | 32 | 723 | 158 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 28 | 780 | 4 | 32 | 844 | 165 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 28 | 678 | 4 | 32 | 742 | 159 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 28 | 780 | 4 | 32 | 844 | 165 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 28 | 682 | 4 | 32 | 746 | 159 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +===================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Light Bulb ` (Debug) | 28 | 782 | 4 | 32 | 846 | 178 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 28 | 681 | 4 | 32 | 745 | 171 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 28 | 744 | 4 | 32 | 808 | 169 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 28 | 642 | 4 | 32 | 706 | 161 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Debug) | 28 | 758 | 4 | 32 | 822 | 168 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Release) | 28 | 639 | 4 | 32 | 703 | 162 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 28 | 699 | 4 | 32 | 763 | 167 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 28 | 605 | 4 | 32 | 669 | 161 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Debug) | 28 | 634 | 4 | 32 | 698 | 169 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Release) | 28 | 542 | 4 | 32 | 606 | 163 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 28 | 745 | 4 | 32 | 809 | 167 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 28 | 639 | 4 | 32 | 703 | 161 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 28 | 730 | 4 | 32 | 794 | 167 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 28 | 630 | 4 | 32 | 694 | 161 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. tab:: nRF5340 DK The following table lists memory requirements for samples running on the :ref:`nRF5340 DK ` (:ref:`nrf5340dk_nrf5340_cpuapp `). - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | - +==================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 32 | 754 | 4 | 32 | 822 | 177 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 32 | 649 | 4 | 32 | 717 | 171 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 32 | 702 | 4 | 32 | 770 | 168 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 32 | 602 | 4 | 32 | 670 | 160 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 32 | 726 | 4 | 32 | 794 | 167 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 32 | 604 | 4 | 32 | 672 | 161 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 32 | 665 | 4 | 32 | 733 | 167 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 32 | 573 | 4 | 32 | 641 | 160 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 32 | 695 | 4 | 32 | 763 | 167 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 32 | 592 | 4 | 32 | 660 | 160 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 32 | 695 | 4 | 32 | 763 | 167 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 32 | 595 | 4 | 32 | 663 | 160 | - +------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +===================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Bridge ` (Wi-Fi external patch) | 32 | 798 | 4 | 32 | 866 | 270 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Debug) | 32 | 709 | 4 | 32 | 777 | 182 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 32 | 605 | 4 | 32 | 673 | 175 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 32 | 671 | 4 | 32 | 739 | 173 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 32 | 567 | 4 | 32 | 635 | 165 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Debug) | 32 | 685 | 4 | 32 | 753 | 173 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Release) | 32 | 563 | 4 | 32 | 631 | 166 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Thread Wi-Fi Switched) | 32 | 728 | 4 | 32 | 796 | 414 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 32 | 626 | 4 | 32 | 694 | 171 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 32 | 530 | 4 | 32 | 598 | 164 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Debug) | 32 | 562 | 4 | 32 | 640 | 173 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Release) | 32 | 468 | 4 | 32 | 536 | 166 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 32 | 672 | 4 | 32 | 740 | 172 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 32 | 563 | 4 | 32 | 631 | 165 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 32 | 657 | 4 | 32 | 725 | 172 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 32 | 555 | 4 | 32 | 623 | 165 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. tab:: Thingy:53 @@ -123,45 +136,85 @@ Values are provided in kilobytes (KB). +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +===============================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Weather Station ` (Debug) | 64 | 766 | 16 | 48 | 894 | 210 | + | :ref:`Weather Station ` (Debug) | 64 | 709 | 16 | 48 | 837 | 215 | +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Weather Station ` (Release) | 64 | 616 | 16 | 48 | 744 | 184 | + | :ref:`Weather Station ` (Release) | 64 | 574 | 16 | 48 | 702 | 188 | +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. tab:: nRF7002 DK The following table lists memory requirements for samples running on the :ref:`nRF7002 DK ` (:ref:`nrf7002dk_nrf5340_cpuapp `). - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | - +============================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Bridge ` (Debug) | 48 | 875 | 4 | 32 | 959 | 265 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Bridge ` (Release) | 48 | 773 | 4 | 32 | 857 | 261 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Debug) | 48 | 886 | 4 | 32 | 970 | 260 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 48 | 767 | 4 | 32 | 851 | 254 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 48 | 881 | 4 | 32 | 965 | 262 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 48 | 769 | 4 | 32 | 853 | 254 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 48 | 907 | 4 | 32 | 991 | 261 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 48 | 771 | 4 | 32 | 855 | 254 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 48 | 847 | 4 | 32 | 931 | 260 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 48 | 742 | 4 | 32 | 826 | 253 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 48 | 873 | 4 | 32 | 957 | 261 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 48 | 758 | 4 | 32 | 842 | 253 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +===================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Bridge ` (Debug) | 48 | 870 | 4 | 32 | 954 | 270 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Bridge ` (Release) | 48 | 798 | 4 | 32 | 882 | 266 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Debug) | 48 | 875 | 4 | 32 | 959 | 266 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 48 | 780 | 4 | 32 | 864 | 259 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 48 | 884 | 4 | 32 | 968 | 268 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 48 | 789 | 4 | 32 | 873 | 259 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Debug) | 48 | 898 | 4 | 32 | 982 | 267 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Release) | 48 | 786 | 4 | 32 | 870 | 259 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 48 | 843 | 4 | 32 | 927 | 266 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 48 | 755 | 4 | 32 | 839 | 258 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Debug) | 48 | 775 | 4 | 32 | 859 | 267 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Release) | 48 | 693 | 4 | 32 | 777 | 259 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 48 | 886 | 4 | 32 | 970 | 266 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 48 | 786 | 4 | 32 | 870 | 258 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + + .. tab:: nRF54L15 PDK + + The following table lists memory requirements for samples running on the :ref:`nRF54L15 PDK ` (:ref:`nrf54l15pdk_nrf54l15 `). + + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +===================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Light Bulb ` (Debug) | 28 | 761 | 4 | 32 | 825 | 175 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 28 | 654 | 4 | 32 | 718 | 167 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 28 | 726 | 4 | 32 | 790 | 166 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 28 | 620 | 4 | 32 | 684 | 157 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 28 | 679 | 4 | 32 | 743 | 164 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 28 | 581 | 4 | 32 | 645 | 156 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Debug) | 28 | 612 | 4 | 32 | 676 | 165 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (LTO Release) | 28 | 553 | 4 | 32 | 617 | 156 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 28 | 726 | 4 | 32 | 790 | 164 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 28 | 616 | 4 | 32 | 680 | 157 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 28 | 708 | 4 | 32 | 772 | 166 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 28 | 606 | 4 | 32 | 670 | 165 | + +-------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. +.. note:: + The results for ``Link-Time Optimization (LTO)`` are based on building the Thread library from sources. + If you use the binary Thread library version, the ROM usage may be higher. + .. _ug_matter_hw_requirements_layouts: Reference Matter memory layouts @@ -509,6 +562,31 @@ For more information about configuration of memory layouts in Matter, see :ref:` | OTP Memory (otp) | 0kB (0x0) | 764B (0x2fc) |- |- |- | +-----------------------------------------+---------------------+-------------------+---------------------+-----------------+-----------------+ + .. tab:: nRF54L15 PDK + + The following memory map is valid for Matter applications running on the :ref:`nRF54L15 PDK ` (:ref:`nrf54l15pdk_nrf54l15 `). + + Application core flash (size: 0x17D000 = 1524kB) + + +-----------------------------------------+---------------------+-------------------+---------------------+-----------------+-------------------+ + | Partition | Offset | Size | Partition elements | Element offset | Element size | + +=========================================+=====================+===================+=====================+=================+===================+ + | Application | 0kB (0x0) | 1488kB (0x164000) |- |- |- | + +-----------------------------------------+---------------------+-------------------+---------------------+-----------------+-------------------+ + | Factory data (factory_data) | 988kB (0x174000) | 4kB (0x1000) |- |- |- | + +-----------------------------------------+---------------------+-------------------+---------------------+-----------------+-------------------+ + | Non-volatile storage (settings_storage) | 992kB (0x175000) | 32kB (0x8000) |- |- |- | + +-----------------------------------------+---------------------+-------------------+---------------------+-----------------+-------------------+ + + Application core SRAM primary (size: 0x40000 = 256kB) + SRAM is located at the address ``0x20000000`` in the memory address space of the application. + + +-----------------------------------------------+---------------------+-------------------+---------------------+-----------------+-----------------+ + | Partition | Offset | Size | Partition elements | Element offset | Element size | + +===============================================+=====================+===================+=====================+=================+=================+ + | Static RAM (sram_primary) | 0kB (0x0) | 256kB (0x40000) |- |- |- | + +-----------------------------------------------+---------------------+-------------------+---------------------+-----------------+-----------------+ + .. You can generate :ref:`Partition Manager's ASCII representation ` of these tables by running the following command for your respective **: @@ -522,3 +600,7 @@ For example, for the ``nrf7002dk_nrf5340_cpuapp`` build target, the command is a .. code-block:: console west build -b nrf7002dk_nrf5340_cpuapp -t partition_manager_report + +.. note:: + + Partition Manager report generation is not available on the :ref:`nRF54L15 PDK ` (:ref:`nrf54l15pdk_nrf54l15 `). diff --git a/doc/nrf/protocols/matter/getting_started/index.rst b/doc/nrf/protocols/matter/getting_started/index.rst index 95d85a8dc2f..0a7d0b1e317 100644 --- a/doc/nrf/protocols/matter/getting_started/index.rst +++ b/doc/nrf/protocols/matter/getting_started/index.rst @@ -47,6 +47,7 @@ These are built from the files available in the official `Matter GitHub reposito advanced_kconfigs transmission_power adding_clusters + matter_api adding_bt_services low_power_configuration memory_optimization diff --git a/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst b/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst index 8ff6ecf8d00..ea70f6feb7e 100644 --- a/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst +++ b/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst @@ -82,11 +82,11 @@ Short idle time and long idle time devices ========================================== The Matter v1.2 specification divides ICD into short idle time (SIT) and long idle time (LIT) devices. -The division is based on the idle mode duration parameter: equal to or shorter than 15 seconds for SIT, and longer than 15 seconds for LIT. +The division is based on the Slow Polling Interval parameter: equal to or shorter than 15 seconds for SIT, and longer than 15 seconds for LIT. -The SIT device behavior is aligned with what was called SED in Matter v.1.1 specification. -The LIT device implementation requires multiple new features, such as Check-In protocol support and ICD client registration. -The division of ICD types and related features were not finalized for Matter v.1.2 and they are marked as provisional, so it is not recommended to use them, though you can find some of the LIT implementation in the Matter SDK and Matter specification. +The SIT device behavior is aligned with what was called SED in Matter v1.1 specification. +The LIT device implementation requires multiple new features, such as Check-In protocol support and ICD client registration. +The division of ICD types and related features were not finalized for Matter v1.2 and they are marked as provisional, so it is not recommended to use them, though you can find some of the LIT implementation in the Matter SDK and Matter specification. Enable low power mode for the selected networking technology ************************************************************ diff --git a/doc/nrf/protocols/matter/getting_started/matter_api.rst b/doc/nrf/protocols/matter/getting_started/matter_api.rst new file mode 100644 index 00000000000..491591ea9ac --- /dev/null +++ b/doc/nrf/protocols/matter/getting_started/matter_api.rst @@ -0,0 +1,258 @@ +.. _ug_matter_gs_matter_api: + +Matter APIs +########### + +.. contents:: + :local: + :depth: 2 + +This section describes the Application Programming Interfaces (APIs) that allow the developer to interact with core components of the Matter stack. +It covers the initialization of Matter modules, user callback registration, and the interaction with Matter Data Model. + +.. _ug_matter_gs_matter_api_overview: + +Overview +******** + +The Matter SDK is the software library that constitutes the reference implementation of the Matter protocol specification. +There is no one unified, documented Matter SDK API that can be referenced when developing a custom application. +Instead, to learn how to interact with the Matter library, a Matter firmware developer must peruse the source code of any of the existing Matter sample applications. +To aid developers, Nordic Semiconductor provides a unified API that wraps initialization of Matter-specific components into more user-friendly high level code. + +The Matter application code in the |NCS| can be divided into the following steps: + +1. Initialization of application-specific components. + This includes initialization of hardware modules and registration of proprietary Bluetooth® LE services. +#. Initialization of the Matter stack. +#. Starting the application main event loop. +#. Interaction between the application and the Matter Data Model. + This is based on the Zigbee Cluster Library (ZCL) callbacks. + +Steps 1 to 3 can be implemented with the use of the nRF Connect Matter API and the utilities provided as a part of |NCS| Matter samples' ``common`` modules (:file:`ncs/nrf/samples/matter/common`). +Step 4 requires ZCL callback functions that must be provided to interact with the Matter Data Model. +These callbacks are specific to the particular configuration of the Data Model (in other words, the supported clusters) and therefore cannot be generalized or abstracted in a more user-friendly form. + +.. note:: + Before the interaction between the application and the Matter Data Model is possible, the source files of the Data Model must be first generated with the `ZCL Advanced Platform`_ (ZAP tool). + Please refer to the :ref:`ug_matter_gs_adding_cluster` for detailed description on how to configure and generate the Matter Data model for your application. + +nRF Connect Matter API +********************** + +The nRF Connect Matter API provides: + +* Initialization API: A set of functions and structures to initialize and manage a Matter server within a Matter application. +* Event handler API: Mechanisms to register and unregister custom functions that handle public events propagated from the Matter stack to the application layer. + +Initialization API +================== + +The initialization API allows developers to configure Matter stack core components, event handlers, and networking backends. + +The following structure collects all Matter interfaces that need to be initialized before starting the Matter Server: + +.. code-block:: C++ + + using CustomInit = CHIP_ERROR (*)(void); + + /** @brief Matter initialization data. + * + * This structure contains all user specific implementations of Matter interfaces + * and custom initialization callbacks that must be initialized in the Matter thread. + */ + struct InitData { + /** @brief Matter stack events handler. */ + chip::DeviceLayer::PlatformManager::EventHandlerFunct mEventHandler{ DefaultEventHandler }; + /** @brief Pointer to the user provided NetworkCommissioning instance. */ + #ifdef CONFIG_CHIP_WIFI + chip::app::Clusters::NetworkCommissioning::Instance *mNetworkingInstance{ &sWiFiCommissioningInstance }; + #else + chip::app::Clusters::NetworkCommissioning::Instance *mNetworkingInstance{ nullptr }; + #endif + /** @brief Pointer to the user provided custom server initialization parameters. */ + chip::CommonCaseDeviceServerInitParams *mServerInitParams{ &sServerInitParamsDefault }; + /** @brief Pointer to the user provided custom device info provider implementation. */ + chip::DeviceLayer::DeviceInfoProviderImpl *mDeviceInfoProvider{ nullptr }; + #ifdef CONFIG_CHIP_FACTORY_DATA + /** @brief Pointer to the user provided FactoryDataProvider implementation. */ + chip::DeviceLayer::FactoryDataProviderBase *mFactoryDataProvider{ &sFactoryDataProviderDefault }; + #endif + #ifdef CONFIG_CHIP_CRYPTO_PSA + /** @brief Pointer to the user provided OperationalKeystore implementation. */ + chip::Crypto::OperationalKeystore *mOperationalKeyStore{ &sOperationalKeystoreDefault }; + #endif + /** @brief Custom code to execute in the Matter main event loop before the server initialization. */ + CustomInit mPreServerInitClbk{ nullptr }; + /** @brief Custom code to execute in the Matter main event loop after the server initialization. */ + CustomInit mPostServerInitClbk{ nullptr }; + + /** @brief Default implementation static objects that will be stripped by the compiler when above + * pointers are overwritten by the application. */ + #ifdef CONFIG_CHIP_WIFI + static chip::app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance; + #endif + static chip::CommonCaseDeviceServerInitParams sServerInitParamsDefault; + #ifdef CONFIG_CHIP_FACTORY_DATA + static chip::DeviceLayer::FactoryDataProvider sFactoryDataProviderDefault; + #endif + #ifdef CONFIG_CHIP_CRYPTO_PSA + static chip::Crypto::PSAOperationalKeystore sOperationalKeystoreDefault; + #endif + }; + +In this structure, each Matter component is defined as a public pointer to its generic interface. +Each pointer is initially assigned with the default concrete implementation of the given interface. +The default implementation object is stripped by the compiler if the user overwrites it with a customized implementation in the application. + +The nRF Connect Matter API contains the following functions that can be used to initialize Matter components in proper order: + +:c:func:`PrepareServer()`: + This function schedules the initialization of Matter components, including memory, server configuration and networking backend. + Depending on the selected Kconfig options, the initialization may also include factory data and operational key storage. + All initialization procedures are scheduled to the Matter thread to provide a synchronization between all components and the application code. + + This function accepts an :c:struct:`InitData` argument that contains the implementation of all required Matter interfaces. + If no argument is provided, this function uses the default-constructed :c:struct:`InitData` temporary object. + After this function is used, the :c:func:`StartServer()` function must be called to start the Matter thread, eventually execute the initialization, and wait to synchronize the caller's thread with the Matter thread. + +:c:func:`StartServer()`: + This is a blocking function that starts the Matter thread and waits until all Matter server components are initialized. + +:c:func:`GetFactoryDataProvider()`: + This function returns the generic pointer to the ``FactoryDataProvider`` object that was set during the initialization. + It can be used when you need to access factory data at the Matter server initialization stage or as a part of the post initialization callback (``mPostServerInitClbk`` in :c:struct:`InitData`). + + This function is only available if the :kconfig:option:`CONFIG_CHIP_FACTORY_DATA` Kconfig option is selected. + +For more details regarding nRF Connect Matter initialization API, refer to the Doxygen commentary in the :file:`ncs/nrf/samples/matter/common/src/app/matter_init.h` header file. + +Event handler API +================= + +The Matter SDK provides a notification scheme based on the public events that are propagated from the Matter stack to the application layer. +The nRF Connect Matter event handler API provides mechanisms to register and unregister custom functions that handle these events within an application. +This module also includes a default handler that is used in nRF Connect SDK Matter samples and applications. + +The specific Matter events that can be handled in the application are listed in the :file:`ncs/modules/lib/matter/src/include/platform/CHIPDeviceEvent.h` header file. +The nRF Connect Matter API contains of the following functions that can be used to handle events: + +:c:func:`RegisterEventHandler()`: + This function is used to register the provided Matter event handler(``EventHandlerFunct``) in a thread-safe manner. + It is safe to call this function in the application after the Matter server has already been initialized. + +:c:func:`UnregisterEventHandler()`: + This function is used to unregister the provided Matter event handler(``EventHandlerFunct``) in a thread-safe manner. + It is safe to call this function in the application after the Matter server has already been initialized. + +:c:func:`DefaultEventHandler()`: + This is an nRF Connect Matter event handler function that is registered in the nRF Connect Matter Initialization API by default. + You can unregister this handler with the :c:func:`UnregisterEventHandler()` function in the application if needed. + +For more details regarding nRF Connect Matter event handler API, refer to the Doxygen commentary in the :file:`ncs/nrf/samples/matter/common/src/app/matter_event_handler.h` header file. + +nRF Connect Matter API usage example +==================================== + +Combining both aforementioned nRF Connect Matter APIs, you can develop an application by following the initialization scheme listed below: + +.. code-block:: C++ + + #include "app/matter_init.h" + + #include + + LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); + + static void CustomMatterEventHandler(const ChipDeviceEvent *event, intptr_t /* unused */) + { + switch (event->Type) { + case DeviceEventType::kCommissioningComplete: + /* Custom code, e.g. control LED */ + break; + } + } + + CHIP_ERROR MatterAppInit() + { + /* Initialize Matter stack */ + ReturnErrorOnFailure(Nrf::Matter::PrepareServer(Nrf::Matter::InitData{ .mPostServerInitClbk = [] { + LOG_INF("Matter server has been initialized."); + return CHIP_NO_ERROR; + } })); + + /* Register custom Matter event handler. */ + ReturnErrorOnFailure(Nrf::Matter::RegisterEventHandler(CustomMatterEventHandler, 0)); + + /* Application specific initialization, e.g. hardware initialization. + + ... + */ + + /* Start Matter thread that will run the scheduled initialization procedure. */ + return Nrf::Matter::StartServer(); + } + +Note that the ``PrepareServer()`` call may contain more fields of the :c:struct:`InitData` being initialized, or can be called without any explicit argument. +If there is no explicit argument, the default initialization will be provided. +For more references and examples on how to leverage the nRF Connect Matter APIs, examine the source code for the :ref:`matter_samples` in the |NCS|. + +Interacting with Matter Data Model +********************************** + +The Matter SDK Data Model interacs with the user's code based on callbacks that can be implemented by the application. +The generic callbacks that are common for Matter applications, regardless of the clusters configuration, are defined in the :file:`ncs/modules/lib/matter/src/app/util/generic-callbacks.h` header file. +The weak implementations of these functions, that can be overwritten in the application, are provided in the :file:`ncs/modules/lib/matter/src/app/util/generic-callback-stubs.cpp` source file. + +For example, the :c:func:`MatterPostAttributeChangeCallback()` function is called by the Matter Data Model engine directly after an attribute value is changed. +The value passed into this callback is the value to which the attribute was set by the framework. +In addition to the value, this function is called with the attribute path ( of ``chip::app::ConcreteAttributePath`` type) that can be used to filter the cluster and particular attribute. +The :c:func:`MatterPostAttributeChangeCallback()` function is useful if you need to provide the synchronization between the Data Model and the application state. +For instance, a Matter device that implements a light bulb may drive the state of the LED based on the ``On/Off`` attribute value. +Every change of this attribute is reported by the aforementioned callback and thus can be captured in the application layer. + +In addition to the :c:func:`MatterPostAttributeChangeCallback()` function, Matter defines other generic callbacks that can be employed in different use cases. +For example, the :c:func:`emberAfExternalAttributeReadCallback()` and :c:func:`emberAfExternalAttributeWriteCallback()` functions can be used to store and handle attributes externally, by bypassing the Matter Data Model framework. +To learn the complete set of Matter generic callbacks, refer to the :file:`ncs/modules/lib/matter/src/app/util/generic-callbacks.h` header file and included Doxygen commentary. +An example implementation of the :c:func:`MatterPostAttributeChangeCallback()` that can be used to control the Door Lock Matter device type is listed below: + +.. code-block:: C++ + + #include + #include + #include + + using namespace ::chip; + using namespace ::chip::app::Clusters; + + void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &attributePath, uint8_t type, + uint16_t size, uint8_t *value) + { + if (attributePath.mClusterId == DoorLock::Id && + attributePath.mAttributeId == DoorLock::Attributes::LockState::Id) { + /* Post events only if current lock state is different than given */ + switch (*value) { + case to_underlying(DlLockState::kLocked): + /* Lock the physical door lock. */ + break; + case to_underlying(DlLockState::kUnlocked): + /* Unlock the physical door lock. */ + break; + default: + break; + } + } + } + +In addition to Matter generic callbacks, the Matter Data Model engine provides callbacks that are cluster-specific. +These callbacks are usually defined as weak functions in the :file:`callback-stub.cpp` file that is generated together with other C++ source files when configuring clusters automatically with the `ZCL Advanced Platform`_ (ZAP tool). +In case of some clusters, however, a different approach is used and related callbacks are defined within the source code that constitutes the implementation of the cluster itself. +As an example, the ``DoorLock`` cluster server implementation defines application callbacks in the :file:`ncs/modules/lib/matter/src/app/clusters/door-lock-server/door-lock-server.h` header file and places the related weak implementations in the :file:`ncs/modules/lib/matter/src/app/clusters/door-lock-server/door-lock-server-callback.cpp` file. + +.. note:: + Most of the Matter Data Model callback function names are prefixed with ``emberAf``. + The reason for this is the fact that the Matter Data Model inherits extensively from the Zigbee Ember Application Framework API. + +In the |NCS|, all Matter samples follow the same convention and implement the described Matter Data Model callbacks in the :file:`zcl_callbacks.cpp` files which are populated as a part of the application source code. +You can review the :file:`zcl_callbacks.cpp` file of any |NCS| Matter sample to find example implementations of various Data Model callbacks. +For instance, you can find the reference implementation of ``DoorLock``-specific Matter Data Model callbacks in the :file:`ncs/nrf/samples/matter/lock/src/zcl_callbacks.cpp` source file. diff --git a/doc/nrf/protocols/matter/getting_started/memory_optimization.rst b/doc/nrf/protocols/matter/getting_started/memory_optimization.rst index 61cc475bc9d..4158160eac7 100644 --- a/doc/nrf/protocols/matter/getting_started/memory_optimization.rst +++ b/doc/nrf/protocols/matter/getting_started/memory_optimization.rst @@ -38,3 +38,15 @@ You can reduce the memory usage of each of these modules in the following ways: .. code-block:: c CHIP_CONFIG_LOG_MODULE_Ble 0 + +Enabling Link Time Optimization (LTO) +************************************* + +You can reduce the memory usage of your Matter application by enabling Link Time Optimization (LTO). + +LTO is an advanced compilation technique that performs optimization across all compiled units of an application at the link stage, rather than within each unit separately. + +To enable LTO, set the :kconfig:option:`CONFIG_LTO` and :kconfig:option:`CONFIG_ISR_TABLES_LOCAL_DECLARATION` Kconfig options to ``y``. + +.. note:: + Support for Link Time Optimization is experimental. diff --git a/doc/nrf/protocols/matter/getting_started/testing/thread_one_otbr.rst b/doc/nrf/protocols/matter/getting_started/testing/thread_one_otbr.rst index ff8f71f7336..6e7952e0d44 100644 --- a/doc/nrf/protocols/matter/getting_started/testing/thread_one_otbr.rst +++ b/doc/nrf/protocols/matter/getting_started/testing/thread_one_otbr.rst @@ -31,8 +31,8 @@ To use this setup, you need the following hardware: * 1x Raspberry Pi Model 3B+ or newer with Ubuntu (20.04 or newer) instead of Raspbian OS * 1x Bluetooth LE dongle (can be embedded inside the PC, like it is on Raspberry Pi) -* 1x nRF52840 DK or nRF52840 Dongle - for the Radio Co-Processor (RCP) device -* 1x nRF52840 DK or nRF5340 DK - for the Matter accessory device (programmed with one of :ref:`matter_samples`) +* 1x nRF52840 DK or nRF52840 Dongle - For the Radio Co-Processor (RCP) device +* 1x nRF52840 DK or nRF5340 DK - For the Matter accessory device (programmed with one of :ref:`matter_samples`) Configuring the environment *************************** @@ -67,9 +67,10 @@ Complete the following steps: 1. Choose one of the following options: - * For Linux only - Use the prebuilt tool package from the `Matter nRF Connect releases`_ GitHub page. + * Use the prebuilt tool package from the `Matter nRF Connect releases`_ GitHub page. Make sure that the package is compatible with your |NCS| version. - * For both Linux and macOS - Build it manually from the source files available in the :file:`modules/lib/matter/examples/chip-tool` directory and using the building instructions from the :doc:`matter:chip_tool_guide` page in the Matter documentation. + * Build manually from the source files available in the :file:`modules/lib/matter/examples/chip-tool` directory. + Use the building instructions from the :doc:`matter:chip_tool_guide` page in the Matter documentation. #. Configure the CHIP Tool controller. Complete the following actions by following the steps in the :doc:`matter:chip_tool_guide` user guide in the Matter documentation: diff --git a/doc/nrf/protocols/matter/getting_started/tools.rst b/doc/nrf/protocols/matter/getting_started/tools.rst index 26f3736f2f2..6eb3feb8fa8 100644 --- a/doc/nrf/protocols/matter/getting_started/tools.rst +++ b/doc/nrf/protocols/matter/getting_started/tools.rst @@ -53,7 +53,7 @@ If you are updating from the |NCS| version earlier than v1.5.0, see the followin .. code-block:: console - wget -O gn.zip https:\ //chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/latest + wget -O gn.zip https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/latest unzip gn.zip rm gn.zip @@ -82,13 +82,13 @@ If you are updating from the |NCS| version earlier than v1.5.0, see the followin .. code-block:: console - curl -o gn.zip -L https:\ //chrome-infra-packages.appspot.com/dl/gn/gn/mac-arm64/+/latest + curl -o gn.zip -L https://chrome-infra-packages.appspot.com/dl/gn/gn/mac-arm64/+/latest * On macOS running on Intel: .. code-block:: console - curl -o gn.zip -L https:\ //chrome-infra-packages.appspot.com/dl/gn/gn/mac-amd64/+/latest + curl -o gn.zip -L https://chrome-infra-packages.appspot.com/dl/gn/gn/mac-amd64/+/latest #. Unzip the archive and then delete it: diff --git a/doc/nrf/protocols/matter/index.rst b/doc/nrf/protocols/matter/index.rst index 8182822f96e..a53cc16c8eb 100644 --- a/doc/nrf/protocols/matter/index.rst +++ b/doc/nrf/protocols/matter/index.rst @@ -20,9 +20,17 @@ The |NCS| allows you to develop applications with different versions of Matter, +--------------------------+-----------------------------------------------------+------------------------+ | nRF Connect SDK version | Matter specification version | `Matter SDK version`_ | +==========================+=====================================================+========================+ -| v2.5.99 (latest) | :ref:`1.2.0 ` | 1.2.0.1 | +| v2.6.99 (latest) | :ref:`1.2.0 ` | 1.2.0.1 | ++--------------------------+ | | +| |release| | | | +--------------------------+-----------------------------------------------------+------------------------+ -| |release| | :ref:`1.1.0 ` | 1.1.0.1 | +| v2.5.2 | :ref:`1.1.0 ` | 1.1.0.1 | ++--------------------------+ | | +| v2.5.1 | | | ++--------------------------+ | | +| v2.5.0 | | | ++--------------------------+ | | +| v2.4.3 | | | +--------------------------+ | | | v2.4.2 | | | +--------------------------+ | | @@ -45,6 +53,11 @@ The |NCS| allows you to develop applications with different versions of Matter, The Matter SDK version is taken as the base for the `dedicated Matter fork`_, which can then include additional changes for each |NCS| release. These changes are listed in the Matter fork section of the |NCS| :ref:`release_notes`. +.. important:: + For Matter over Thread samples, starting with |NCS| releases after v2.5.2, the default cryptography backend is Arm PSA Crypto API instead of Mbed TLS, which was used in earlier versions. + To :ref:`inherit Thread certification ` from Nordic Semiconductor, you must use the PSA Crypto API backend. + See the :ref:`migration guide ` to learn about all changes if you are migrating from an earlier version of the |NCS|. + For more information about Matter compatibility, see :ref:`ug_matter_overview_dev_model_support` and :ref:`supported Matter features per SoC `. See :ref:`matter_samples` for the list of available samples, :ref:`Matter Weather Station ` or :ref:`Matter bridge ` for specific Matter application. diff --git a/doc/nrf/protocols/matter/overview/data_model.rst b/doc/nrf/protocols/matter/overview/data_model.rst index 286268565d2..1f2d0bcd601 100644 --- a/doc/nrf/protocols/matter/overview/data_model.rst +++ b/doc/nrf/protocols/matter/overview/data_model.rst @@ -333,7 +333,7 @@ Appliance device types | Laundry Washer | A Laundry Washer represents a device that is capable of laundering consumer | Certifiable | | | | items. Any laundry washer product may utilize this device type. | | | +--------------------+------------------------------------------------------------------------------+---------------------+---------------------------------------+ -| Refidgerator | A Refrigerator represents a device that contains one or more cabinets that | Certifiable | | +| Refrigerator | A Refrigerator represents a device that contains one or more cabinets that | Certifiable | | | | are capable of chilling or freezing food. Examples of consumer products that | | | | | may make use of this device type include refrigerators, freezers, and wine | | | | | coolers. | | | diff --git a/doc/nrf/protocols/matter/overview/dev_model.rst b/doc/nrf/protocols/matter/overview/dev_model.rst index 9f0729c8908..c54a0d2cf8d 100644 --- a/doc/nrf/protocols/matter/overview/dev_model.rst +++ b/doc/nrf/protocols/matter/overview/dev_model.rst @@ -34,16 +34,25 @@ For more information about Matter architecture and Matter in the |NCS|, read :re Supported Matter versions in the |NCS| ====================================== -The following table lists Matter versions supported in the |NCS|, with a brief overview of changes and the release date. - -+-----------------+--------------------------------------------------------------------------------------------------------------------------------+---------------------+ -| Matter version | Overview of changes | Release date | -+=================+================================================================================================================================+=====================+ -| 1.1.0 | - Improved Intermittently Connected Device (ICD) support: more :ref:`ug_matter_configuring_optional_persistent_subscriptions`. | May 18, 2023 | -| | - Enhancements and bug fixes for Matter Specification, Certification Test Plan, and the Matter SDK. | | -+-----------------+--------------------------------------------------------------------------------------------------------------------------------+---------------------+ -| 1.0.0 | Initial version of the Matter specification. | November 2, 2022 | -+-----------------+--------------------------------------------------------------------------------------------------------------------------------+---------------------+ +The following table lists Matter versions supported in the |NCS|, with a brief overview of changes. +The table also lists the release date for that Matter specification version, and the version of the |NCS| that added support for it. + ++-----------------+----------------------------------------------------------------------------------------------------------+-----------------------+------------------+ +| | | Specification | |NCS| version | +| Matter version | Overview of changes | release date | | ++=================+==========================================================================================================+=======================+==================+ +| 1.2.0 | - Introduced support for the ICD Management cluster. | October 23, 2023 | v2.6.0 | +| | - Added the Product Appearance attribute in the Basic Information cluster. | | | +| | - Added nine new :ref:`device types `: | | | +| | Refrigerator, Room Air Conditioner, Dishwasher, Laundry Washer, Robotic Vacuum Cleaner, | | | +| | Smoke CO Alarm, Air Quality Sensor, Air Purifier, and Fan. | | | ++-----------------+----------------------------------------------------------------------------------------------------------+-----------------------+------------------+ +| 1.1.0 | - Improved Intermittently Connected Device (ICD) support: | May 18, 2023 | v2.4.0 | +| | more :ref:`ug_matter_configuring_optional_persistent_subscriptions`. | | | +| | - Enhancements and bug fixes for Matter Specification, Certification Test Plan, and the Matter SDK. | | | ++-----------------+----------------------------------------------------------------------------------------------------------+-----------------------+------------------+ +| 1.0.0 | Initial version of the Matter specification. | October 4, 2022 | v2.1.2 | ++-----------------+----------------------------------------------------------------------------------------------------------+-----------------------+------------------+ .. _ug_matter_overview_dev_model_ecosystems: diff --git a/doc/nrf/protocols/matter/overview/images/matter_platform_design_nRF53_wifi_switching.svg b/doc/nrf/protocols/matter/overview/images/matter_platform_design_nRF53_wifi_switching.svg index a8672c6ca28..4b595b602be 100644 --- a/doc/nrf/protocols/matter/overview/images/matter_platform_design_nRF53_wifi_switching.svg +++ b/doc/nrf/protocols/matter/overview/images/matter_platform_design_nRF53_wifi_switching.svg @@ -2,7 +2,7 @@